From a62570f4c827542405408b449c3508af9e0e18fe Mon Sep 17 00:00:00 2001 From: lizheng Date: Mon, 6 Dec 2021 10:25:21 +0800 Subject: [PATCH] =?UTF-8?q?!104=20=E6=94=AF=E6=8C=81hdi=20gpu=E6=B7=B7?= =?UTF-8?q?=E5=90=88=E5=90=88=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I3685730a57a8785eeee60fb967bb0abefd50232b Signed-off-by: lizheng --- BUILD.gn | 4 + frameworks/dumper/BUILD.gn | 178 ++++++ frameworks/dumper/gdumper.ini | 15 + .../include/graphic_dumper_command_line.h | 63 ++ .../include/graphic_dumper_helper_impl.h | 133 ++++ .../dumper/include/graphic_dumper_hilog.h | 50 ++ .../dumper/include/graphic_dumper_server.h | 116 ++++ .../dumper/include/graphic_dumper_tree.h | 56 ++ .../dumper/include/graphic_dumper_util.h | 28 + ...c_dumper_client_listener_death_recipient.h | 37 ++ .../graphic_dumper_client_listener_proxy.h | 38 ++ .../ipc/graphic_dumper_client_listener_stub.h | 33 + .../ipc/graphic_dumper_command_proxy.h | 41 ++ .../include/ipc/graphic_dumper_command_stub.h | 40 ++ ...hic_dumper_info_listener_death_recipient.h | 34 ++ .../ipc/graphic_dumper_info_listener_proxy.h | 36 ++ .../ipc/graphic_dumper_info_listener_stub.h | 33 + .../ipc/graphic_dumper_service_proxy.h | 37 ++ .../include/ipc/graphic_dumper_service_stub.h | 38 ++ .../ipc/igraphic_dumper_client_listener.h | 38 ++ .../include/ipc/igraphic_dumper_command.h | 48 ++ .../ipc/igraphic_dumper_info_listener.h | 36 ++ .../include/ipc/igraphic_dumper_service.h | 41 ++ .../src/graphic_dumper_command_line.cpp | 268 +++++++++ .../src/graphic_dumper_command_line_main.cpp | 23 + .../dumper/src/graphic_dumper_helper.cpp | 66 ++ .../dumper/src/graphic_dumper_helper_impl.cpp | 329 ++++++++++ .../dumper/src/graphic_dumper_server.cpp | 567 ++++++++++++++++++ .../dumper/src/graphic_dumper_server_main.cpp | 29 + frameworks/dumper/src/graphic_dumper_tree.cpp | 106 ++++ frameworks/dumper/src/graphic_dumper_util.cpp | 38 ++ ...dumper_client_listener_death_recipient.cpp | 28 + .../graphic_dumper_client_listener_proxy.cpp | 74 +++ .../graphic_dumper_client_listener_stub.cpp | 56 ++ .../src/ipc/graphic_dumper_command_proxy.cpp | 148 +++++ .../src/ipc/graphic_dumper_command_stub.cpp | 128 ++++ ...c_dumper_info_listener_death_recipient.cpp | 29 + .../graphic_dumper_info_listener_proxy.cpp | 50 ++ .../ipc/graphic_dumper_info_listener_stub.cpp | 50 ++ .../src/ipc/graphic_dumper_service_proxy.cpp | 84 +++ .../src/ipc/graphic_dumper_service_stub.cpp | 91 +++ frameworks/wm/BUILD.gn | 2 + .../wm/include/input_listener_manager.h | 22 +- .../wm/include/virtual_display_option_impl.h | 55 ++ frameworks/wm/include/window_manager_impl.h | 4 + frameworks/wm/src/input_listener_manager.cpp | 81 ++- frameworks/wm/src/virtual_display_option.cpp | 25 + .../wm/src/virtual_display_option_impl.cpp | 102 ++++ frameworks/wm/src/window_impl.cpp | 3 +- frameworks/wm/src/window_manager_impl.cpp | 64 ++ frameworks/wm/src/wl_dma_buffer_factory.cpp | 2 +- .../mock/mock_iwindow_manager_service.h | 2 + frameworks/wmserver/BUILD.gn | 1 - frameworks/wmserver/protocol/wms.xml | 23 + frameworks/wmserver/src/wmserver.c | 552 +++++++++++++---- frameworks/wmserver/src/wmserver.h | 2 + .../include/window_manager_service_proxy.h | 4 +- .../window_manager_service_client_impl.cpp | 5 +- .../src/window_manager_service_proxy.cpp | 26 +- frameworks/wmtest/BUILD.gn | 10 + frameworks/wmtest/frameworks/main.cpp | 34 +- frameworks/wmtest/frameworks/main_option.cpp | 29 + frameworks/wmtest/frameworks/main_option.h | 32 + .../wmtest/frameworks/native_test_class.cpp | 5 +- .../wmtest/frameworks/native_test_class.h | 6 +- frameworks/wmtest/test/dumper_test_1.cpp | 155 +++++ frameworks/wmtest/test/dumper_test_1.h | 19 + frameworks/wmtest/test/pref_native_test_1.cpp | 18 +- .../wmtest/test/wmclient_native_test_2.cpp | 26 +- .../wmtest/test/wmclient_native_test_33.cpp | 127 ++++ .../wmtest/test/wmclient_native_test_33.h | 19 + .../wmtest/test/wmclient_native_test_34.cpp | 96 +++ .../wmtest/test/wmclient_native_test_34.h | 19 + .../wmtest/test/wmclient_native_test_35.cpp | 128 ++++ .../wmtest/test/wmclient_native_test_35.h | 19 + graphic.cfg | 5 + graphic.rc | 6 + .../innerkits/dumper/graphic_dumper_helper.h | 55 ++ .../wmclient/virtual_display_option.h | 46 ++ .../innerkits/wmclient/window_manager.h | 5 + .../innerkits/wmclient/window_manager_type.h | 14 + .../wmservice/iwindow_manager_service.h | 3 + .../wmservice/window_manager_service_type.h | 8 - ohos.build | 4 + utils/BUILD.gn | 4 + utils/option_parser/BUILD.gn | 41 ++ utils/option_parser/export/option_parser.h | 153 +++++ utils/option_parser/src/option_parser.cpp | 274 +++++++++ 88 files changed, 5467 insertions(+), 205 deletions(-) create mode 100755 frameworks/dumper/BUILD.gn create mode 100644 frameworks/dumper/gdumper.ini create mode 100644 frameworks/dumper/include/graphic_dumper_command_line.h create mode 100644 frameworks/dumper/include/graphic_dumper_helper_impl.h create mode 100644 frameworks/dumper/include/graphic_dumper_hilog.h create mode 100644 frameworks/dumper/include/graphic_dumper_server.h create mode 100644 frameworks/dumper/include/graphic_dumper_tree.h create mode 100644 frameworks/dumper/include/graphic_dumper_util.h create mode 100644 frameworks/dumper/include/ipc/graphic_dumper_client_listener_death_recipient.h create mode 100644 frameworks/dumper/include/ipc/graphic_dumper_client_listener_proxy.h create mode 100644 frameworks/dumper/include/ipc/graphic_dumper_client_listener_stub.h create mode 100644 frameworks/dumper/include/ipc/graphic_dumper_command_proxy.h create mode 100644 frameworks/dumper/include/ipc/graphic_dumper_command_stub.h create mode 100644 frameworks/dumper/include/ipc/graphic_dumper_info_listener_death_recipient.h create mode 100644 frameworks/dumper/include/ipc/graphic_dumper_info_listener_proxy.h create mode 100644 frameworks/dumper/include/ipc/graphic_dumper_info_listener_stub.h create mode 100644 frameworks/dumper/include/ipc/graphic_dumper_service_proxy.h create mode 100644 frameworks/dumper/include/ipc/graphic_dumper_service_stub.h create mode 100644 frameworks/dumper/include/ipc/igraphic_dumper_client_listener.h create mode 100644 frameworks/dumper/include/ipc/igraphic_dumper_command.h create mode 100644 frameworks/dumper/include/ipc/igraphic_dumper_info_listener.h create mode 100644 frameworks/dumper/include/ipc/igraphic_dumper_service.h create mode 100644 frameworks/dumper/src/graphic_dumper_command_line.cpp create mode 100644 frameworks/dumper/src/graphic_dumper_command_line_main.cpp create mode 100644 frameworks/dumper/src/graphic_dumper_helper.cpp create mode 100644 frameworks/dumper/src/graphic_dumper_helper_impl.cpp create mode 100644 frameworks/dumper/src/graphic_dumper_server.cpp create mode 100644 frameworks/dumper/src/graphic_dumper_server_main.cpp create mode 100644 frameworks/dumper/src/graphic_dumper_tree.cpp create mode 100644 frameworks/dumper/src/graphic_dumper_util.cpp create mode 100644 frameworks/dumper/src/ipc/graphic_dumper_client_listener_death_recipient.cpp create mode 100644 frameworks/dumper/src/ipc/graphic_dumper_client_listener_proxy.cpp create mode 100644 frameworks/dumper/src/ipc/graphic_dumper_client_listener_stub.cpp create mode 100644 frameworks/dumper/src/ipc/graphic_dumper_command_proxy.cpp create mode 100644 frameworks/dumper/src/ipc/graphic_dumper_command_stub.cpp create mode 100644 frameworks/dumper/src/ipc/graphic_dumper_info_listener_death_recipient.cpp create mode 100644 frameworks/dumper/src/ipc/graphic_dumper_info_listener_proxy.cpp create mode 100644 frameworks/dumper/src/ipc/graphic_dumper_info_listener_stub.cpp create mode 100644 frameworks/dumper/src/ipc/graphic_dumper_service_proxy.cpp create mode 100644 frameworks/dumper/src/ipc/graphic_dumper_service_stub.cpp create mode 100644 frameworks/wm/include/virtual_display_option_impl.h create mode 100644 frameworks/wm/src/virtual_display_option.cpp create mode 100644 frameworks/wm/src/virtual_display_option_impl.cpp create mode 100644 frameworks/wmtest/frameworks/main_option.cpp create mode 100644 frameworks/wmtest/frameworks/main_option.h create mode 100644 frameworks/wmtest/test/dumper_test_1.cpp create mode 100644 frameworks/wmtest/test/dumper_test_1.h create mode 100644 frameworks/wmtest/test/wmclient_native_test_33.cpp create mode 100644 frameworks/wmtest/test/wmclient_native_test_33.h create mode 100644 frameworks/wmtest/test/wmclient_native_test_34.cpp create mode 100644 frameworks/wmtest/test/wmclient_native_test_34.h create mode 100644 frameworks/wmtest/test/wmclient_native_test_35.cpp create mode 100644 frameworks/wmtest/test/wmclient_native_test_35.h create mode 100644 interfaces/innerkits/dumper/graphic_dumper_helper.h create mode 100644 interfaces/innerkits/wmclient/virtual_display_option.h create mode 100644 utils/option_parser/BUILD.gn create mode 100644 utils/option_parser/export/option_parser.h create mode 100644 utils/option_parser/src/option_parser.cpp diff --git a/BUILD.gn b/BUILD.gn index daadf9264d..2b87dcc3d4 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -69,3 +69,7 @@ group("libgl") { ] public_deps += libgl } + +group("libgraphic_dumper_client") { + public_deps = [ "frameworks/dumper:libgraphic_dumper_client" ] +} diff --git a/frameworks/dumper/BUILD.gn b/frameworks/dumper/BUILD.gn new file mode 100755 index 0000000000..5a143b2ea1 --- /dev/null +++ b/frameworks/dumper/BUILD.gn @@ -0,0 +1,178 @@ +# Copyright (c) 2021 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") + +## Build libgraphic_dumper_client.so {{{ +config("graphic_dumper_client_config") { + visibility = [ ":*" ] + + include_dirs = [ + "include", + "//utils/system/safwk/native/include", + ] + + cflags = [ + "-Wall", + "-Werror", + "-g3", + ] +} + +config("graphic_dumper_client_public_config") { + include_dirs = [ + "//foundation/graphic/standard/interfaces/innerkits/dumper", + "//foundation/graphic/standard/interfaces/innerkits/common", + "//utils/native/base/include", + ] +} + +ohos_shared_library("libgraphic_dumper_client") { + sources = [ + "src/graphic_dumper_helper.cpp", + "src/graphic_dumper_helper_impl.cpp", + "src/ipc/graphic_dumper_client_listener_stub.cpp", + "src/ipc/graphic_dumper_service_proxy.cpp", + ] + + configs = [ ":graphic_dumper_client_config" ] + + public_configs = [ ":graphic_dumper_client_public_config" ] + + deps = [ + "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + ] + + external_deps = [ "ipc:ipc_core" ] + + public_deps = [ "//utils/native/base:utils" ] + + part_name = "graphic_standard" + subsystem_name = "graphic" +} + +## Build libgraphic_dumper_client.so }}} + +## Build graphic_dumper_server {{{ +config("graphic_dumper_server_config") { + visibility = [ ":*" ] + + include_dirs = [ + "include", + "//utils/system/safwk/native/include", + ] + + cflags = [ + "-Wall", + "-Werror", + "-g3", + ] +} + +ohos_executable("graphic_dumper_server") { + install_enable = true + + sources = [ + "src/graphic_dumper_server.cpp", + "src/graphic_dumper_server_main.cpp", + "src/graphic_dumper_tree.cpp", + "src/graphic_dumper_util.cpp", + "src/ipc/graphic_dumper_client_listener_death_recipient.cpp", + "src/ipc/graphic_dumper_client_listener_proxy.cpp", + "src/ipc/graphic_dumper_command_stub.cpp", + "src/ipc/graphic_dumper_info_listener_death_recipient.cpp", + "src/ipc/graphic_dumper_info_listener_proxy.cpp", + "src/ipc/graphic_dumper_service_stub.cpp", + ] + + configs = [ + ":graphic_dumper_server_config", + ":graphic_dumper_client_public_config", + ] + + deps = [ + "//third_party/zlib:libz", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "samgr_standard:samgr_proxy", + ] + + part_name = "graphic_standard" + subsystem_name = "graphic" +} + +## Build graphic_dumper_server }}} + +## Build gdumper {{{ +config("gdumper_config") { + visibility = [ ":*" ] + + include_dirs = [ + "include", + "//utils/system/safwk/native/include", + ] + + cflags = [ + "-Wall", + "-Werror", + "-g3", + ] +} + +ohos_executable("gdumper") { + install_enable = true + + sources = [ + "src/graphic_dumper_command_line.cpp", + "src/graphic_dumper_command_line_main.cpp", + "src/graphic_dumper_util.cpp", + "src/ipc/graphic_dumper_command_stub.cpp", + "src/ipc/graphic_dumper_info_listener_stub.cpp", + "src/ipc/graphic_dumper_service_stub.cpp", + ] + + configs = [ + ":gdumper_config", + ":graphic_dumper_client_public_config", + ] + + deps = [ + "//foundation/graphic/standard/utils:promise", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "samgr_standard:samgr_proxy", + ] + + part_name = "graphic_standard" + subsystem_name = "graphic" +} + +## Build gdumper }}} + +## Install gdumper.ini to /system/etc/./gdumper.ini {{{ +ohos_prebuilt_etc("gdumper.ini") { + source = "gdumper.ini" + relative_install_dir = "." + part_name = "graphic_standard" + subsystem_name = "graphic" +} +## Install gdumper.ini to /system/etc/./gdumper.ini }}} diff --git a/frameworks/dumper/gdumper.ini b/frameworks/dumper/gdumper.ini new file mode 100644 index 0000000000..9cac8da51a --- /dev/null +++ b/frameworks/dumper/gdumper.ini @@ -0,0 +1,15 @@ +# Copyright (c) 2021 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. + +# [dumper] +# A.B=true diff --git a/frameworks/dumper/include/graphic_dumper_command_line.h b/frameworks/dumper/include/graphic_dumper_command_line.h new file mode 100644 index 0000000000..4dd422bb32 --- /dev/null +++ b/frameworks/dumper/include/graphic_dumper_command_line.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_COMMAND_LINE_H +#define FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_COMMAND_LINE_H + +#include +#include + +#include "ipc/graphic_dumper_info_listener_stub.h" +#include "ipc/igraphic_dumper_command.h" + +namespace OHOS { +using DumperArgs = struct { + bool wait = false; + std::string dumpTag = {}; + std::string logTag = {}; + std::string getCfgKey = {}; + std::string setCfgKey = {}; + std::string setCfgValue = {}; +}; + +class GraphicDumperCommandLine : public GraphicDumperInfoListenerStub { +public: + static sptr GetInstance(); + virtual void OnInfoComing(const std::string &info) override; + GSError Main(int32_t argc, char *argv[]); + +private: + GraphicDumperCommandLine() = default; + ~GraphicDumperCommandLine() = default; + static inline sptr instance_; + + void HandlerOfArgs(); + GSError OptionParse(const char option); + GSError Parse(int32_t argc, char *argv[]); + GSError InitSA(int32_t systemAbilityId); + + sptr service_; + DumperArgs dumperArgs_ = {}; +}; + +class GDumperCommandDeathRecipient : public IRemoteObject::DeathRecipient { +public: + GDumperCommandDeathRecipient() = default; + virtual ~GDumperCommandDeathRecipient() = default; + void OnRemoteDied(const wptr &object) override; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_COMMAND_LINE_H diff --git a/frameworks/dumper/include/graphic_dumper_helper_impl.h b/frameworks/dumper/include/graphic_dumper_helper_impl.h new file mode 100644 index 0000000000..cd52cd1c9c --- /dev/null +++ b/frameworks/dumper/include/graphic_dumper_helper_impl.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_HELPER_IMPL_H +#define FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_HELPER_IMPL_H + +#include +#include +#include +#include +#include + +#include + +#include "ipc/graphic_dumper_service_proxy.h" +#include "ipc/graphic_dumper_client_listener_stub.h" + +namespace OHOS { +namespace { +class GraphicDumperClientListener; +} + +using ConfigFuncMapPtr = std::unique_ptr>; +using DumpFuncMapPtr = std::unique_ptr>; + +class GraphicDumperHelperImpl : public GraphicDumperHelper { + friend class GraphicDumperClientListener; +public: + static sptr GetInstance(); + + virtual GSError SendInfo(const std::string &tag, const char *fmt, ...) override; + virtual int32_t AddConfigChangeListener(const std::string &tag, OnConfigChangeFunc func) override; + virtual GSError RemoveConfigChangeListener(const int32_t listenerId) override; + virtual int32_t AddDumpListener(const std::string &tag, OnDumpFunc func) override; + virtual GSError RemoveDumpListener(const int32_t listenerId) override; + + void SetConnectState(bool state); + +private: + GraphicDumperHelperImpl(); + virtual ~GraphicDumperHelperImpl() = default; + static inline sptr currentHelper = nullptr; + static void SetNoopInstance(); + + GSError Init(); + GSError InitSA(int32_t systemAbilityId); + GSError AddClientListener(const std::string &tag); + void DispenseOnConfigChange(const std::string &tag, const std::string &val); + void DispenseOnDump(const std::string &tag); + + std::mutex initMutex_; + std::atomic_int64_t requestConnectTime = 0; + std::atomic_bool serverConnected = false; + sptr service_ = nullptr; + + std::mutex clientListenerMutex_; + sptr listener_ = nullptr; + + int32_t onConfigChangeFuncId_ = 0; + std::mutex onConfigChangeMutex_; + std::map onConfigChangeMap_; + + int32_t onDumperFuncId_ = 0; + std::mutex onDumperFuncsMutex_; + std::map onDumpFuncsMap_; + + struct InfoStruct { + std::string tag; + std::string info; + }; + std::mutex cacheInfoMutex_; + std::vector cacheInfo_; +}; + +class GDumperServiceDeathRecipient : public IRemoteObject::DeathRecipient { +public: + GDumperServiceDeathRecipient() = default; + virtual ~GDumperServiceDeathRecipient() = default; + void OnRemoteDied(const wptr &object) override; +}; + +class GraphicDumperHelperNoop : public GraphicDumperHelper { +public: + virtual GSError SendInfo(const std::string &tag, const char *fmt, ...) + { + return GSERROR_CONNOT_CONNECT_SERVER; + } + virtual int32_t AddConfigChangeListener(const std::string &tag, OnConfigChangeFunc func) + { + return 0; + } + virtual GSError RemoveConfigChangeListener(const int32_t listenerId) + { + return GSERROR_CONNOT_CONNECT_SERVER; + } + virtual int32_t AddDumpListener(const std::string &tag, OnDumpFunc func) + { + return 0; + } + virtual GSError RemoveDumpListener(const int32_t listenerId) + { + return GSERROR_CONNOT_CONNECT_SERVER; + } +}; + +namespace { +class GraphicDumperClientListener : public GraphicDumperClientListenerStub { +public: + GraphicDumperClientListener(sptr& helper); + virtual ~GraphicDumperClientListener() = default; + + void OnConfigChange(const std::string &tag, const std::string &val) override; + void OnDump(const std::string &tag) override; + +private: + sptr helperImpl_ = nullptr; +}; +} // namespace +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_HELPER_IMPL_H diff --git a/frameworks/dumper/include/graphic_dumper_hilog.h b/frameworks/dumper/include/graphic_dumper_hilog.h new file mode 100644 index 0000000000..d107358666 --- /dev/null +++ b/frameworks/dumper/include/graphic_dumper_hilog.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPER_INCLUDE_GRAPHIC_DUMPER_HILOG_H +#define FRAMEWORKS_DUMPER_INCLUDE_GRAPHIC_DUMPER_HILOG_H + +#include "hilog/log.h" +namespace OHOS { +#define GD_CPRINTF(func, fmt, ...) func(LABEL, "<%{public}d>" fmt, __LINE__, ##__VA_ARGS__) + +#define GDLOGD(fmt, ...) GD_CPRINTF(HiviewDFX::HiLog::Debug, fmt, ##__VA_ARGS__) +#define GDLOGI(fmt, ...) GD_CPRINTF(HiviewDFX::HiLog::Info, fmt, ##__VA_ARGS__) +#define GDLOGW(fmt, ...) GD_CPRINTF(HiviewDFX::HiLog::Warn, fmt, ##__VA_ARGS__) +#define GDLOGE(fmt, ...) GD_CPRINTF(HiviewDFX::HiLog::Error, fmt, ##__VA_ARGS__) + +#define GDLOGFD(fmt, ...) GDLOGD("%{public}s: " fmt, __func__, ##__VA_ARGS__) +#define GDLOGFI(fmt, ...) GDLOGI("%{public}s: " fmt, __func__, ##__VA_ARGS__) +#define GDLOGFW(fmt, ...) GDLOGW("%{public}s: " fmt, __func__, ##__VA_ARGS__) +#define GDLOGFE(fmt, ...) GDLOGE("%{public}s: " fmt, __func__, ##__VA_ARGS__) + +#define GDLOG_SUCCESS(fmt, ...) GDLOGI("Success, Way: " fmt, ##__VA_ARGS__) +#define GDLOG_FAILURE(fmt, ...) GDLOGE("Failure, Reason: " fmt, ##__VA_ARGS__) +#define GDLOG_FAILURE_NO(gs_error) GDLOG_FAILURE("%{public}s", GSErrorStr(gs_error).c_str()) +#define GDLOG_FAILURE_RET(gs_error) \ + do { \ + GDLOG_FAILURE_NO(gs_error); \ + return gs_error; \ + } while (0) +#define GDLOG_FAILURE_API(api, ret) GDLOG_FAILURE(#api " failed with %{public}s", GSErrorStr(ret).c_str()) + +#define GDLOG_ERROR(errno, fmt, ...) \ + GDLOGE(fmt ", means %{public}s", ##__VA_ARGS__, strerror(errno)) + +#define GDLOG_ERROR_API(ret, api) \ + GDLOG_ERROR(ret, #api " failed with %{public}d", ret) +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPER_INCLUDE_GRAPHIC_DUMPER_HILOG_H diff --git a/frameworks/dumper/include/graphic_dumper_server.h b/frameworks/dumper/include/graphic_dumper_server.h new file mode 100644 index 0000000000..2aa77a8990 --- /dev/null +++ b/frameworks/dumper/include/graphic_dumper_server.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_SERVER_H +#define FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_SERVER_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "graphic_dumper_tree.h" +#include "ipc/igraphic_dumper_client_listener.h" +#include "ipc/igraphic_dumper_command.h" +#include "ipc/igraphic_dumper_info_listener.h" +#include "ipc/igraphic_dumper_service.h" + +namespace OHOS { +struct LogBuffer { + bool canSave = false; + bool needSave = false; + bool sync = false; + uint32_t index = 0; + uint32_t size[2] = {0}; + std::mutex mutex[2]; + std::vector>> vec; + std::string mask = {}; +}; + +struct LogBlock { + uint32_t size; + uint32_t length; + uint8_t data[0]; +}; + +struct ConfigTags { + uint32_t id = 0; + sptr listener = nullptr; + std::vector tags = {}; +}; + +class GraphicDumperServer : public RefBase { +public: + static sptr GetInstance(); + int32_t Init(); + + GSError AddConfigListener(const std::string &tag, sptr &listener); + GSError RemoveConfigListener(sptr object); + GSError GetConfig(const std::string &k, std::string &v); + GSError SetConfig(const std::string &k, const std::string &v); + GSError Dump(const std::string &tag); + + GSError AddInfoListener(sptr &listener); + GSError RemoveInfoListener(const wptr &object); + GSError InfoHandle(const std::string &tag, const std::string &info); + GSError GetLog(const std::string &tag, const std::string &info); + +private: + GraphicDumperServer() = default; + virtual ~GraphicDumperServer() = default; + static inline sptr instance_; + + int32_t StartServer(int32_t systemAbility, sptr obj); + int32_t ReadDefaultConfig(); + void AddConfigDeathRecipient(sptr &object); + bool HaveConfigDeathRecipient(sptr &object); + bool HaveObject(const sptr &obj); + void VisitEach(const TreeNodePtr &node, std::function func); + void RemoveNode(std::vector &vec, TreeNodePtr &sub, uint32_t &listenerId); + void DispenseConfig(const TreeNodePtr &node, const std::string &k, const std::string &v); + void DispenseDump(const TreeNodePtr &node, const std::string &tag); + + void AddInfoDeathRecipient(sptr &object); + bool HaveInfoDeathRecipient(sptr &object); + void SendToInfoListener(const std::string &info); + static void SaveLog(std::any server); + GSError LogHandle(const std::string &tag, const std::string &info); + +private: + std::mutex infoListenersMutex_; + std::map, sptr> infoListeners_; + std::map, sptr> infoListenerDeathRecipientMap_; + + uint32_t objectId_ = 0; + std::map configTagsMap_; + std::map, uint32_t> objectIdMap_; + std::mutex treeMutex_; + const TreeNodePtr root = std::make_shared(); + + LogBuffer logBuf_; + uint32_t logBlockSize_ = 0; + std::mutex logBlockVectorMutex_; + std::vector> logBlockVector_; + std::unique_ptr thread_ = nullptr; + std::map, sptr> configListenerDeathRecipientMap_; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_SERVER_H diff --git a/frameworks/dumper/include/graphic_dumper_tree.h b/frameworks/dumper/include/graphic_dumper_tree.h new file mode 100644 index 0000000000..56773c32e2 --- /dev/null +++ b/frameworks/dumper/include/graphic_dumper_tree.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_TREE_H +#define FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_TREE_H + +#include +#include +#include +#include +#include + +#include + +#include "ipc/igraphic_dumper_client_listener.h" + +namespace OHOS { +class GraphicDumperTree; +using TreeNodePtr = std::shared_ptr; +using TreeNodeVisitFunc = std::function; +using TreeNodeMap = std::map; + +class GraphicDumperTree { +public: + TreeNodePtr GetSetNode(const std::string str); + bool HasNode(const std::string str); + bool IsEmptyNode(); + void EraseNode(const std::string &tag); + std::string GetTag(); + void SetValue(const std::string str); + std::string GetValue(); + void AddListenerId(uint32_t &listenerId); + void RemoveListenerId(uint32_t &listenerId); + std::vector GetListenerIds() const; + void Foreach(TreeNodeVisitFunc func) const; + +private: + std::string tag_ = ""; + std::string value_ = ""; + std::unique_ptr nodeMap_ = nullptr; + std::vector listenerIds_ = {}; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_TREE_H diff --git a/frameworks/dumper/include/graphic_dumper_util.h b/frameworks/dumper/include/graphic_dumper_util.h new file mode 100644 index 0000000000..682775dd88 --- /dev/null +++ b/frameworks/dumper/include/graphic_dumper_util.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPER_INCLUDE_GRAPHIC_DUMPER_UTIL_H +#define FRAMEWORKS_DUMPER_INCLUDE_GRAPHIC_DUMPER_UTIL_H + +#include +#include + +namespace OHOS { +constexpr int32_t CFGTERMSIZE = 2; + +std::vector Split(std::string src, const std::string &splitStr); +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPER_INCLUDE_GRAPHIC_DUMPER_UTIL_H diff --git a/frameworks/dumper/include/ipc/graphic_dumper_client_listener_death_recipient.h b/frameworks/dumper/include/ipc/graphic_dumper_client_listener_death_recipient.h new file mode 100644 index 0000000000..a505068912 --- /dev/null +++ b/frameworks/dumper/include/ipc/graphic_dumper_client_listener_death_recipient.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_CLIENT_LISTENER_DEATH_RECIPIENT_H +#define FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_CLIENT_LISTENER_DEATH_RECIPIENT_H + +#include + +#include +#include +#include +#include + +#include "ipc/igraphic_dumper_service.h" + +namespace OHOS { +class GraphicDumperClientListenerDeathRecipient : public IRemoteObject::DeathRecipient { +public: + GraphicDumperClientListenerDeathRecipient() = default; + virtual ~GraphicDumperClientListenerDeathRecipient() = default; + void OnRemoteDied(const wptr &object) override; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_SERVICE_H diff --git a/frameworks/dumper/include/ipc/graphic_dumper_client_listener_proxy.h b/frameworks/dumper/include/ipc/graphic_dumper_client_listener_proxy.h new file mode 100644 index 0000000000..a3d875485e --- /dev/null +++ b/frameworks/dumper/include/ipc/graphic_dumper_client_listener_proxy.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_CLIENT_LISTENER_PROXY_H +#define FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_CLIENT_LISTENER_PROXY_H + +#include +#include + +#include "ipc/igraphic_dumper_client_listener.h" + +namespace OHOS { +class GraphicDumperClientListenerProxy : public IRemoteProxy { +public: + GraphicDumperClientListenerProxy(const sptr& impl); + virtual ~GraphicDumperClientListenerProxy() = default; + + void OnConfigChange(const std::string &tag, const std::string &val) override; + void OnDump(const std::string &tag) override; + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_CLIENT_LISTENER_STUB_H diff --git a/frameworks/dumper/include/ipc/graphic_dumper_client_listener_stub.h b/frameworks/dumper/include/ipc/graphic_dumper_client_listener_stub.h new file mode 100644 index 0000000000..7ea82b9edc --- /dev/null +++ b/frameworks/dumper/include/ipc/graphic_dumper_client_listener_stub.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_CLIENT_LISTENER_STUB_H +#define FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_CLIENT_LISTENER_STUB_H + +#include +#include +#include + +#include "ipc/igraphic_dumper_client_listener.h" + +namespace OHOS { +class GraphicDumperClientListenerStub : public IRemoteStub { +public: + virtual int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, + MessageParcel& reply, MessageOption& option) override; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_CLIENT_LISTENER_STUB_H diff --git a/frameworks/dumper/include/ipc/graphic_dumper_command_proxy.h b/frameworks/dumper/include/ipc/graphic_dumper_command_proxy.h new file mode 100644 index 0000000000..fef09c8af6 --- /dev/null +++ b/frameworks/dumper/include/ipc/graphic_dumper_command_proxy.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_COMMAND_PROXY_H +#define FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_COMMAND_PROXY_H + +#include +#include + +#include "ipc/igraphic_dumper_command.h" + +namespace OHOS { +class GraphicDumperCommandProxy : public IRemoteProxy { +public: + GraphicDumperCommandProxy(const sptr& impl); + virtual ~GraphicDumperCommandProxy() = default; + + GSError GetConfig(const std::string &k, std::string &v) override; + GSError SetConfig(const std::string &k, const std::string &v) override; + GSError Dump(const std::string &key) override; + GSError GetLog(const std::string &tag, std::string &log) override; + GSError AddInfoListener(const std::string &tag, sptr &listener) override; + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_COMMAND_STUB_H diff --git a/frameworks/dumper/include/ipc/graphic_dumper_command_stub.h b/frameworks/dumper/include/ipc/graphic_dumper_command_stub.h new file mode 100644 index 0000000000..f71ace8947 --- /dev/null +++ b/frameworks/dumper/include/ipc/graphic_dumper_command_stub.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_COMMAND_STUB_H +#define FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_COMMAND_STUB_H + +#include +#include +#include + +#include "ipc/igraphic_dumper_command.h" + +namespace OHOS { +class GraphicDumperCommandStub : public IRemoteStub { +public: + virtual int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, + MessageParcel& reply, MessageOption& option) override; + virtual GSError GetConfig(const std::string &k, std::string &v) override; + virtual GSError SetConfig(const std::string &k, const std::string &v) override; + + using IPCObjectStub::Dump; + virtual GSError Dump(const std::string &tag) override; + virtual GSError GetLog(const std::string &tag, std::string &log) override; + virtual GSError AddInfoListener(const std::string &tag, sptr &listener) override; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_COMMAND_H diff --git a/frameworks/dumper/include/ipc/graphic_dumper_info_listener_death_recipient.h b/frameworks/dumper/include/ipc/graphic_dumper_info_listener_death_recipient.h new file mode 100644 index 0000000000..707e2d0f03 --- /dev/null +++ b/frameworks/dumper/include/ipc/graphic_dumper_info_listener_death_recipient.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_INFO_LISTENER_DEATH_RECIPIENT_H +#define FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_INFO_LISTENER_DEATH_RECIPIENT_H + +#include +#include +#include + +#include "ipc/igraphic_dumper_command.h" + +namespace OHOS { +class GraphicDumperInfoListenerDeathRecipient : public IRemoteObject::DeathRecipient { +public: + GraphicDumperInfoListenerDeathRecipient() = default; + virtual ~GraphicDumperInfoListenerDeathRecipient() = default; + void OnRemoteDied(const wptr &object) override; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_COMMAND_H diff --git a/frameworks/dumper/include/ipc/graphic_dumper_info_listener_proxy.h b/frameworks/dumper/include/ipc/graphic_dumper_info_listener_proxy.h new file mode 100644 index 0000000000..6a3c07b51f --- /dev/null +++ b/frameworks/dumper/include/ipc/graphic_dumper_info_listener_proxy.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_INFO_LISTENER_PROXY_H +#define FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_INFO_LISTENER_PROXY_H + +#include +#include + +#include "ipc/igraphic_dumper_info_listener.h" + +namespace OHOS { +class GraphicDumperInfoListenerProxy : public IRemoteProxy { +public: + GraphicDumperInfoListenerProxy(const sptr& impl); + virtual ~GraphicDumperInfoListenerProxy() = default; + void OnInfoComing(const std::string &info) override; + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_INFO_LISTENER_STUB_H diff --git a/frameworks/dumper/include/ipc/graphic_dumper_info_listener_stub.h b/frameworks/dumper/include/ipc/graphic_dumper_info_listener_stub.h new file mode 100644 index 0000000000..51835e30e6 --- /dev/null +++ b/frameworks/dumper/include/ipc/graphic_dumper_info_listener_stub.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_INFO_LISTENER_STUB_H +#define FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_INFO_LISTENER_STUB_H + +#include +#include +#include + +#include "ipc/igraphic_dumper_info_listener.h" + +namespace OHOS { +class GraphicDumperInfoListenerStub : public IRemoteStub { +public: + virtual int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, + MessageParcel& reply, MessageOption& option) override; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_INFO_LISTENER_STUB_H diff --git a/frameworks/dumper/include/ipc/graphic_dumper_service_proxy.h b/frameworks/dumper/include/ipc/graphic_dumper_service_proxy.h new file mode 100644 index 0000000000..8fb929ab00 --- /dev/null +++ b/frameworks/dumper/include/ipc/graphic_dumper_service_proxy.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_SERVICE_PROXY_H +#define FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_SERVICE_PROXY_H + +#include +#include + +#include "ipc/igraphic_dumper_service.h" + +namespace OHOS { +class GraphicDumperServiceProxy : public IRemoteProxy { +public: + GraphicDumperServiceProxy(const sptr& impl); + virtual ~GraphicDumperServiceProxy() = default; + GSError AddClientListener(const std::string &tag, sptr &listener) override; + GSError SendInfo(const std::string &tag, const std::string &info) override; + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_SERVICE_PROXY_H diff --git a/frameworks/dumper/include/ipc/graphic_dumper_service_stub.h b/frameworks/dumper/include/ipc/graphic_dumper_service_stub.h new file mode 100644 index 0000000000..d1381210a3 --- /dev/null +++ b/frameworks/dumper/include/ipc/graphic_dumper_service_stub.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_SERVICE_STUB_H +#define FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_SERVICE_STUB_H + +#include + +#include +#include +#include +#include + +#include "ipc/igraphic_dumper_service.h" + +namespace OHOS { +class GraphicDumperServiceStub : public IRemoteStub { +public: + virtual int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, + MessageParcel& reply, MessageOption& option) override; + GSError AddClientListener(const std::string &tag, sptr &listener) override; + GSError SendInfo(const std::string &tag, const std::string &info) override; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_SERVICE_H diff --git a/frameworks/dumper/include/ipc/igraphic_dumper_client_listener.h b/frameworks/dumper/include/ipc/igraphic_dumper_client_listener.h new file mode 100644 index 0000000000..b87ea13d3a --- /dev/null +++ b/frameworks/dumper/include/ipc/igraphic_dumper_client_listener.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_IGRAPHIC_DUMPER_CLIENT_LISTENER_H +#define FRAMEWORKS_DUMPRE_INCLUDE_IGRAPHIC_DUMPER_CLIENT_LISTENER_H + +#include + +#include + +namespace OHOS { +class IGraphicDumperClientListener : public IRemoteBroker { +public: + virtual void OnConfigChange(const std::string &tag, const std::string &val) = 0; + virtual void OnDump(const std::string &key) = 0; + DECLARE_INTERFACE_DESCRIPTOR(u"IGraphicDumperClientListener"); + +protected: + enum { + IGRAPHIC_DUMPER_CLIENT_LISTENER_ON_CONFIG_CHANGE, + IGRAPHIC_DUMPER_CLIENT_LISTENER_ON_DUMP, + }; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_IGRAPHIC_DUMPER_CLIENT_LISTENER_H diff --git a/frameworks/dumper/include/ipc/igraphic_dumper_command.h b/frameworks/dumper/include/ipc/igraphic_dumper_command.h new file mode 100644 index 0000000000..a265ff1935 --- /dev/null +++ b/frameworks/dumper/include/ipc/igraphic_dumper_command.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_IGRAPHIC_DUMPER_COMMAND_H +#define FRAMEWORKS_DUMPRE_INCLUDE_IGRAPHIC_DUMPER_COMMAND_H + +#include + +#include + +#include "graphic_common.h" +#include "ipc/igraphic_dumper_info_listener.h" + +namespace OHOS { +class IGraphicDumperCommand : public IRemoteBroker { +public: + virtual GSError GetConfig(const std::string &k, std::string &v) = 0; + virtual GSError SetConfig(const std::string &k, const std::string &v) = 0; + virtual GSError Dump(const std::string &tag) = 0; + virtual GSError GetLog(const std::string &tag, std::string &log) = 0; + virtual GSError AddInfoListener(const std::string &tag, sptr &listener) = 0; + + DECLARE_INTERFACE_DESCRIPTOR(u"IGraphicDumperCommand"); + +protected: + enum { + IGRAPHIC_DUMPER_COMMAND_GET_CONFIG, + IGRAPHIC_DUMPER_COMMAND_SET_CONFIG, + IGRAPHIC_DUMPER_COMMAND_DUMP, + IGRAPHIC_DUMPER_COMMAND_GET_LOG, + IGRAPHIC_DUMPER_COMMAND_ADD_INFO_LISTENER, + }; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_IGRAPHIC_DUMPER_COMMAND_H diff --git a/frameworks/dumper/include/ipc/igraphic_dumper_info_listener.h b/frameworks/dumper/include/ipc/igraphic_dumper_info_listener.h new file mode 100644 index 0000000000..7005a0f4c3 --- /dev/null +++ b/frameworks/dumper/include/ipc/igraphic_dumper_info_listener.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_IGRAPHIC_DUMPER_INFO_LISTENER_H +#define FRAMEWORKS_DUMPRE_INCLUDE_IGRAPHIC_DUMPER_INFO_LISTENER_H + +#include + +#include + +namespace OHOS { +class IGraphicDumperInfoListener : public IRemoteBroker { +public: + virtual void OnInfoComing(const std::string &info) = 0; + DECLARE_INTERFACE_DESCRIPTOR(u"IGraphicDumperInfoListener"); + +protected: + enum { + IGRAPHIC_DUMPER_INFO_LISTENER_ON_INFO_COMING, + }; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_IGRAPHIC_DUMPER_INFO_LISTENER_H diff --git a/frameworks/dumper/include/ipc/igraphic_dumper_service.h b/frameworks/dumper/include/ipc/igraphic_dumper_service.h new file mode 100644 index 0000000000..8b4a69f40e --- /dev/null +++ b/frameworks/dumper/include/ipc/igraphic_dumper_service.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_IGRAPHIC_DUMPER_SERVICE_H +#define FRAMEWORKS_DUMPRE_INCLUDE_IGRAPHIC_DUMPER_SERVICE_H + +#include + +#include + +#include "graphic_common.h" +#include "ipc/igraphic_dumper_client_listener.h" + +namespace OHOS { +class IGraphicDumperService : public IRemoteBroker { +public: + virtual GSError AddClientListener(const std::string &tag, sptr &listener) = 0; + virtual GSError SendInfo(const std::string &tag, const std::string &info) = 0; + DECLARE_INTERFACE_DESCRIPTOR(u"IGraphicDumperService"); + +protected: + enum { + IGRAPHIC_DUMPER_SERVICE_ADD_CLIENT_LISTENER, + IGRAPHIC_DUMPER_SERVICE_SEND_INFO, + }; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_IGRAPHIC_DUMPER_SERVICE_H diff --git a/frameworks/dumper/src/graphic_dumper_command_line.cpp b/frameworks/dumper/src/graphic_dumper_command_line.cpp new file mode 100644 index 0000000000..c5b92a3247 --- /dev/null +++ b/frameworks/dumper/src/graphic_dumper_command_line.cpp @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2021 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 "graphic_dumper_command_line.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "graphic_dumper_hilog.h" +#include "graphic_dumper_util.h" + +namespace OHOS { +namespace { +constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0, "GraphicDumperCommandLine" }; +constexpr int SLEEP_TIME = 5 * 1000; +Promise signalPromise; + +static void Helper() +{ + std::cerr << + "Usage: [options]\n" + "options include:\n" + " -h --help show this message.\n" + " -w --wait wait mode; listen for new prints.\n" + " -g , --get \n" + " get config with key.\n" + " -s =, --set =\n" + " set config of key is equal to value.\n" + " -l --log \n" + " read log with tag.\n" + " -d --dump \n" + " read dump info with tag.\n" + " read all dump info with --all.\n" + << std::endl; +} +} // namespace + +sptr GraphicDumperCommandLine::GetInstance() +{ + if (instance_ == nullptr) { + static std::mutex mutex; + std::lock_guard guard(mutex); + if (instance_ == nullptr) { + instance_ = new GraphicDumperCommandLine(); + } + } + return instance_; +} + +void GraphicDumperCommandLine::OnInfoComing(const std::string &info) +{ + std::cerr << info.c_str() << std::endl; +} + +void Handler(int signal) +{ + switch (signal) { + case SIGINT: + case SIGTERM: + case SIGTSTP: + case SIGQUIT: + case SIGHUP: { + signalPromise.Resolve(signal); + break; + } + default: + break; + } +} + +void SignalInit() +{ + std::signal(SIGINT, Handler); + std::signal(SIGKILL, Handler); + std::signal(SIGTERM, Handler); + std::signal(SIGTSTP, Handler); + std::signal(SIGQUIT, Handler); + std::signal(SIGHUP, Handler); +} + +GSError GraphicDumperCommandLine::Main(int32_t argc, char *argv[]) +{ + GSError iRet = GSERROR_OK; + if (argc <= 1) { + Helper(); + return iRet; + } + + iRet = Parse(argc, argv); + if (iRet != GSERROR_OK) { + return iRet; + } + + SignalInit(); + + iRet = InitSA(GRAPHIC_DUMPER_COMMAND_SA_ID); + if (iRet != GSERROR_OK) { + std::cerr << "Init SA failed: " << iRet << std::endl; + return iRet; + } + + sptr listener = this; + iRet = service_->AddInfoListener("", listener); + if (iRet != GSERROR_OK) { + std::cerr << "Add info listener failed: " << iRet << std::endl; + return iRet; + } + + HandlerOfArgs(); + usleep(SLEEP_TIME); + return GSERROR_OK; +} + +void GraphicDumperCommandLine::HandlerOfArgs() +{ + if (!dumperArgs_.dumpTag.empty()) { + service_->Dump("*#dp#*." + dumperArgs_.dumpTag); + std::cerr << "get dump with tag:" << dumperArgs_.dumpTag.c_str() << std::endl; + } + if (!dumperArgs_.logTag.empty()) { + std::string getLog = {}; + std::cerr << "get log with tag:" << dumperArgs_.logTag.c_str() << std::endl; + service_->GetLog(dumperArgs_.logTag, getLog); + std::cerr << "log is" << getLog.c_str() << std::endl; + } + if (!dumperArgs_.getCfgKey.empty()) { + std::string getCfgValue = {}; + service_->GetConfig(dumperArgs_.getCfgKey, getCfgValue); + std::cerr << "get cfg with key:" << dumperArgs_.getCfgKey.c_str() << "value is:" + << getCfgValue.c_str() << std::endl; + } + if ((!dumperArgs_.setCfgKey.empty()) && (!dumperArgs_.setCfgKey.empty())) { + service_->SetConfig(dumperArgs_.setCfgKey, dumperArgs_.setCfgValue); + std::cerr << "set cfg with key:" << dumperArgs_.setCfgKey.c_str() << "value is:" + << dumperArgs_.setCfgValue.c_str() << std::endl; + } + if (dumperArgs_.wait) { + signalPromise.Await(); + } +} + +GSError GraphicDumperCommandLine::OptionParse(const char option) +{ + switch (option) { + case 'h': { + Helper(); + return GSERROR_OK; + break; + } + case 'w': { + dumperArgs_.wait = true; + break; + } + case 'g': { + dumperArgs_.getCfgKey = optarg; + break; + } + case 's': { + auto ret = Split(optarg, "="); + if (ret.size() != CFGTERMSIZE) { + std::cerr << "Parameter format error." << std::endl; + return GSERROR_INVALID_OPERATING; + } + dumperArgs_.setCfgKey = ret[0]; + dumperArgs_.setCfgValue = ret[1]; + break; + } + case 'l': { + dumperArgs_.logTag = optarg; + break; + } + case 'd': { + dumperArgs_.dumpTag = optarg; + break; + } + default: { + std::cerr << "Command not found." << std::endl; + return GSERROR_INVALID_OPERATING; + break; + } + } // switch + return GSERROR_OK; +} + +GSError GraphicDumperCommandLine::Parse(int32_t argc, char *argv[]) +{ + int optIndex = 0; + static const struct option longOptions[] = { + { "help", no_argument, nullptr, 'h' }, + { "wait", no_argument, nullptr, 'w' }, + { "log", required_argument, nullptr, 'l' }, + { "dump", required_argument, nullptr, 'd' }, + { "get", required_argument, nullptr, 'g' }, + { "set", required_argument, nullptr, 's' }, + {nullptr, 0, nullptr, 0} + }; + + while (true) { + int opt = getopt_long(argc, argv, "hwg:s:l:d:", longOptions, &optIndex); + if (opt == -1) { + break; + } + auto ret = OptionParse(opt); + if (ret != GSERROR_OK) { + return ret; + } + } // while + return GSERROR_OK; +} + +GSError GraphicDumperCommandLine::InitSA(int32_t systemAbilityId) +{ + if (service_ != nullptr) { + GDLOG_SUCCESS("_instance != nullptr"); + return GSERROR_OK; + } + + auto sm = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (sm == nullptr) { + GDLOG_FAILURE_RET(GSERROR_CONNOT_CONNECT_SAMGR); + } + + auto remoteObject = sm->GetSystemAbility(systemAbilityId); + if (remoteObject == nullptr) { + GDLOG_FAILURE_RET(GSERROR_CONNOT_CONNECT_SERVER); + } + + sptr deathRecipient = new GDumperCommandDeathRecipient(); + if ((remoteObject->IsProxyObject()) && (!remoteObject->AddDeathRecipient(deathRecipient))) { + GDLOGFE("Failed to add death recipient"); + } + + service_ = iface_cast(remoteObject); + if (service_ == nullptr) { + GDLOG_FAILURE_RET(GSERROR_PROXY_NOT_INCLUDE); + } + + GDLOG_SUCCESS("service_ = iface_cast"); + return GSERROR_OK; +} + +void GDumperCommandDeathRecipient::OnRemoteDied(const wptr &object) +{ + GDLOGFE("Command server Died!"); + std::raise(SIGQUIT); +} +} // namespace OHOS diff --git a/frameworks/dumper/src/graphic_dumper_command_line_main.cpp b/frameworks/dumper/src/graphic_dumper_command_line_main.cpp new file mode 100644 index 0000000000..435f143773 --- /dev/null +++ b/frameworks/dumper/src/graphic_dumper_command_line_main.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021 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 "graphic_dumper_command_line.h" + +using namespace OHOS; + +int32_t main(int32_t argc, char *argv[]) +{ + return GraphicDumperCommandLine::GetInstance()->Main(argc, argv); +} diff --git a/frameworks/dumper/src/graphic_dumper_helper.cpp b/frameworks/dumper/src/graphic_dumper_helper.cpp new file mode 100644 index 0000000000..7af2de5dba --- /dev/null +++ b/frameworks/dumper/src/graphic_dumper_helper.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include + +#include "graphic_dumper_helper_impl.h" + +namespace OHOS { +sptr GraphicDumperHelper::GetInstance() +{ + return GraphicDumperHelperImpl::GetInstance(); +} +} // namespace OHOS + +int SendInfo(const char* tag, const char *fmt, ...) +{ + constexpr int infoSize = 4096; + char info[infoSize]; + va_list args; + va_start(args, fmt); + int ret = vsnprintf_s(info, sizeof(info), (sizeof(info) - 1), fmt, args); + if (ret < 0) { + return 0; + } + va_end(args); + return OHOS::GraphicDumperHelperImpl::GetInstance()->SendInfo(std::string(tag), "%s", info); +} + +int AddConfigChangeListener(const char* tag, OnConfigChangeFuncPtr func) +{ + auto cfunc = [func](const std::string &a, const std::string &b) { + func(a.c_str(), b.c_str()); + }; + return OHOS::GraphicDumperHelperImpl::GetInstance()->AddConfigChangeListener(std::string(tag), cfunc); +} + +int RemoveConfigChangeListener(int listenerId) +{ + return OHOS::GraphicDumperHelperImpl::GetInstance()->RemoveConfigChangeListener(listenerId); +} + +int AddDumpListener(const char* tag, OnDumpFuncPtr func) +{ + return OHOS::GraphicDumperHelperImpl::GetInstance()->AddDumpListener(std::string(tag), func); +} + +int RemoveDumpListener(int listenerId) +{ + return OHOS::GraphicDumperHelperImpl::GetInstance()->RemoveDumpListener(listenerId); +} diff --git a/frameworks/dumper/src/graphic_dumper_helper_impl.cpp b/frameworks/dumper/src/graphic_dumper_helper_impl.cpp new file mode 100644 index 0000000000..d1595cca0d --- /dev/null +++ b/frameworks/dumper/src/graphic_dumper_helper_impl.cpp @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2021 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 "graphic_dumper_helper_impl.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include "graphic_dumper_hilog.h" +#include "ipc/igraphic_dumper_command.h" + +namespace OHOS { +namespace { +constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0, "GraphicDumperHelperImpl" }; +constexpr int INFO_SIZE_MAX = 4096; +} + +GraphicDumperClientListener::GraphicDumperClientListener(sptr& helper) + : helperImpl_(helper) +{ +} + +void GraphicDumperClientListener::OnConfigChange(const std::string &tag, const std::string &val) +{ + GDLOGI("%{public}s -> %{public}s", tag.c_str(), val.c_str()); + if (helperImpl_) { + helperImpl_->DispenseOnConfigChange(tag, val); + } +} + +void GraphicDumperClientListener::OnDump(const std::string &tag) +{ + if (helperImpl_) { + std::string flag = "*#dp#*."; + if (tag.find(flag) == 0) { + std::string sTag = tag.substr(flag.length()); + helperImpl_->DispenseOnDump(sTag); + } + } +} + +sptr GraphicDumperHelperImpl::GetInstance() +{ + if (currentHelper == nullptr) { + static std::mutex mutex; + std::lock_guard guard(mutex); + if (currentHelper == nullptr) { + currentHelper = new GraphicDumperHelperImpl(); + } + } + return currentHelper; +} + +GraphicDumperHelperImpl::GraphicDumperHelperImpl() +{ +} + +void GraphicDumperHelperImpl::SetNoopInstance() +{ + static std::mutex mutex; + std::lock_guard guard(mutex); + currentHelper = new GraphicDumperHelperNoop(); +} + +GSError GraphicDumperHelperImpl::Init() +{ + std::lock_guard lock(initMutex_); + if (serverConnected) { + return GSERROR_OK; + } + if (access("/data/gdumper_enable", F_OK) != 0) { + SetNoopInstance(); + return GSERROR_NOT_SUPPORT; + } + + auto now = std::chrono::steady_clock::now().time_since_epoch(); + auto nowTime = (int64_t)std::chrono::duration_cast(now).count(); + constexpr int64_t reconnectTime = 1000; + if ((nowTime - requestConnectTime) < reconnectTime) { + return GSERROR_OUT_OF_RANGE; + } + requestConnectTime = nowTime; + GSError ret = InitSA(GRAPHIC_DUMPER_SERVICE_SA_ID); + if (ret != GSERROR_OK) { + return ret; + } + + { + std::lock_guard guard(onConfigChangeMutex_); + for (const auto& iter : onConfigChangeMap_) { + ret = AddClientListener(iter.first); + if (ret != GSERROR_OK) { + return ret; + } + } + } + + { + std::lock_guard guard(onDumperFuncsMutex_); + for (const auto& iter : onDumpFuncsMap_) { + ret = AddClientListener(iter.first); + if (ret != GSERROR_OK) { + return ret; + } + } + } + + { + std::lock_guard guard(cacheInfoMutex_); + for (const auto& infoStruct : cacheInfo_) { + ret = service_->SendInfo(infoStruct.tag, infoStruct.info); + GDLOG_SUCCESS("SendInfo is %{public}d", ret); + } + cacheInfo_.clear(); + cacheInfo_.shrink_to_fit(); + } + return ret; +} + +GSError GraphicDumperHelperImpl::InitSA(int32_t systemAbilityId) +{ + if (serverConnected) { + return GSERROR_OK; + } + + auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (sam == nullptr) { + GDLOG_FAILURE_RET(GSERROR_CONNOT_CONNECT_SAMGR); + } + + auto remoteObject = sam->GetSystemAbility(systemAbilityId); + if (remoteObject == nullptr) { + GDLOG_FAILURE_RET(GSERROR_CONNOT_CONNECT_SERVER); + } + + sptr deathRecipient = new GDumperServiceDeathRecipient(); + if ((remoteObject->IsProxyObject()) && (!remoteObject->AddDeathRecipient(deathRecipient))) { + GDLOGFE("Failed to add death recipient"); + } + + service_ = iface_cast(remoteObject); + if (service_ == nullptr) { + GDLOG_FAILURE_RET(GSERROR_PROXY_NOT_INCLUDE); + } + serverConnected = true; + GDLOG_SUCCESS("service_ = iface_cast"); + return GSERROR_OK; +} + +GSError GraphicDumperHelperImpl::AddClientListener(const std::string &tag) +{ + if (Init() != GSERROR_OK) { + return GSERROR_CONNOT_CONNECT_SERVER; + } + + if (listener_ == nullptr) { + std::lock_guard guard(clientListenerMutex_); + if (listener_ == nullptr) { + sptr helper = this; + listener_ = new GraphicDumperClientListener(helper); + } + } + return service_->AddClientListener(tag, listener_); +} + +GSError GraphicDumperHelperImpl::SendInfo(const std::string &tag, const char *fmt, ...) +{ + char info[INFO_SIZE_MAX]; // clear by vsnprintf + { + static std::mutex sprintfMutex_; + std::lock_guard lock(sprintfMutex_); + va_list args; + va_start(args, fmt); + int ret = vsnprintf_s(info, sizeof(info), (sizeof(info) - 1), fmt, args); + if (ret < 0) { + return GSERROR_INVALID_ARGUMENTS; + } + va_end(args); + } + GSError retInit = Init(); + if (retInit == GSERROR_OK) { + return service_->SendInfo(tag, std::string(info)); + GDLOGFE("SendInfo is ok"); + } else if (retInit == GSERROR_NOT_SUPPORT) { + return retInit; + } else { + struct InfoStruct infoStruct = { + .tag = tag, + .info = info, + }; + std::lock_guard guard(cacheInfoMutex_); + cacheInfo_.push_back(infoStruct); + return GSERROR_OK; + } +} + +int32_t GraphicDumperHelperImpl::AddConfigChangeListener(const std::string &tag, OnConfigChangeFunc func) +{ + { + std::lock_guard guard(onConfigChangeMutex_); + if (onConfigChangeMap_.find(tag) != onConfigChangeMap_.end()) { + (*onConfigChangeMap_[tag])[++onConfigChangeFuncId_] = func; + return onConfigChangeFuncId_; + } + } + int ret = AddClientListener(tag); + if (ret != GSERROR_OK) { + return 0; + } + auto onConfigChangeFuncs = std::make_unique>(); + (*onConfigChangeFuncs)[++onConfigChangeFuncId_] = func; + onConfigChangeMap_[tag] = std::move(onConfigChangeFuncs); + return onConfigChangeFuncId_; +} + +GSError GraphicDumperHelperImpl::RemoveConfigChangeListener(const int32_t listenerId) +{ + std::lock_guard guard(onConfigChangeMutex_); + for (auto& [k, v] : onConfigChangeMap_) { + if (v->find(listenerId) != v->end()) { + v->erase(listenerId); + return GSERROR_OK; + } + } + return GSERROR_INVALID_ARGUMENTS; +} + +int32_t GraphicDumperHelperImpl::AddDumpListener(const std::string &tag, OnDumpFunc func) +{ + std::lock_guard guard(onDumperFuncsMutex_); + if (onDumpFuncsMap_.find(tag) != onDumpFuncsMap_.end()) { + (*onDumpFuncsMap_[tag])[++onDumperFuncId_] = func; + return onDumperFuncId_; + } + auto dumpTag = "*#dp#*." + tag; + int ret = AddClientListener(dumpTag); + if (ret != GSERROR_OK) { + return 0; + } + auto onDumpFuncs = std::make_unique>(); + (*onDumpFuncs)[++onDumperFuncId_] = func; + onDumpFuncsMap_[tag] = std::move(onDumpFuncs); + return onDumperFuncId_; +} + +GSError GraphicDumperHelperImpl::RemoveDumpListener(const int32_t listenerId) +{ + std::lock_guard guard(onDumperFuncsMutex_); + for (auto& [k, v] : onDumpFuncsMap_) { + if (v->find(listenerId) != v->end()) { + v->erase(listenerId); + return GSERROR_OK; + } + } + return GSERROR_INVALID_ARGUMENTS; +} + +void GraphicDumperHelperImpl::SetConnectState(bool state) +{ + GDLOGFI(""); + serverConnected = state; +} + +void GraphicDumperHelperImpl::DispenseOnConfigChange(const std::string &tag, const std::string &val) +{ + GDLOGI("%{public}s -> %{public}s", tag.c_str(), val.c_str()); + std::lock_guard guard(onConfigChangeMutex_); + if (onConfigChangeMap_.empty()) { + return; + } + if (!onConfigChangeMap_[tag]->empty()) { + for (const auto &[id, func] : *onConfigChangeMap_[tag]) { + func(tag, val); + } + } +} + +void GraphicDumperHelperImpl::DispenseOnDump(const std::string &tag) +{ + std::lock_guard guard(onDumperFuncsMutex_); + if (onDumpFuncsMap_.empty()) { + return; + } + + if (tag == "--all") { + for (const auto& [t, mapPtr] : onDumpFuncsMap_) { + if (mapPtr != nullptr) { + for (const auto &[id, func] : *mapPtr) { + func(); + } + } + } + return; + } + + if (onDumpFuncsMap_.find(tag) != onDumpFuncsMap_.end()) { + if (onDumpFuncsMap_[tag] != nullptr) { + for (const auto &[id, func] : *onDumpFuncsMap_[tag]) { + func(); + } + } + } +} + +void GDumperServiceDeathRecipient::OnRemoteDied(const wptr &object) +{ + auto helper = GraphicDumperHelperImpl::GetInstance(); + auto helperImpl = reinterpret_cast(helper.GetRefPtr()); + helperImpl->SetConnectState(false); +} +} // namespace OHOS diff --git a/frameworks/dumper/src/graphic_dumper_server.cpp b/frameworks/dumper/src/graphic_dumper_server.cpp new file mode 100644 index 0000000000..66f37deb20 --- /dev/null +++ b/frameworks/dumper/src/graphic_dumper_server.cpp @@ -0,0 +1,567 @@ +/* + * Copyright (c) 2021 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 "graphic_dumper_server.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ipc/graphic_dumper_info_listener_death_recipient.h" +#include "ipc/graphic_dumper_client_listener_death_recipient.h" +#include "ipc/graphic_dumper_service_stub.h" +#include "ipc/graphic_dumper_command_stub.h" +#include "graphic_dumper_hilog.h" +#include "graphic_dumper_util.h" + +namespace OHOS { +namespace { +constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0, "GraphicDumperServer" }; +constexpr int SLEEP_TIME = 500 * 1000; +constexpr uint32_t LOG_BUF_SIZE_MAX = 192 * 1024; +constexpr uint32_t LOG_BLOCK_SIZE_MAX = 4 * 1000 * 1024; +constexpr uint32_t LOG_VEC_SIZE = 2; +constexpr const char *GDUMPER_INI_PATH = "/system/etc/gdumper.ini"; + +std::string& Trim (std::string &s) +{ + std::regex fmt("\\s"); + s = std::regex_replace(s, fmt, ""); + return s; +} + +void StrLogRomveTag(bool getAll, const std::string &tag, + const std::string &strIn, std::string &strOut) +{ + auto pos = strIn.find_first_of("| ["); + constexpr int offset = 2; + if (pos == std::string::npos) { + pos = 0; + } else { + pos += offset; + } + if (getAll) { + strOut += strIn.substr(pos); + } else if (strIn.compare(0, tag.size(), tag) == 0) { + strOut += strIn.substr(pos); + } +} +} // namespace + +sptr GraphicDumperServer::GetInstance() +{ + if (instance_ == nullptr) { + static std::mutex mutex; + std::lock_guard guard(mutex); + if (instance_ == nullptr) { + instance_ = new GraphicDumperServer(); + } + } + return instance_; +} + +int32_t GraphicDumperServer::Init() +{ + int32_t ret = 0; + ret = ReadDefaultConfig(); + if (ret) { + GDLOGI("Read default config error with %d.\n", ret); + } + + for (auto& s : logBuf_.size) { + s = 0; + logBuf_.vec.push_back(std::make_unique>()); + } + + sptr service = new GraphicDumperServiceStub(); + ret = StartServer(GRAPHIC_DUMPER_SERVICE_SA_ID, service); + if (ret) { + GDLOGI("Start graphic dumper service failed: %d\n", ret); + return ret; + } + + sptr command = new GraphicDumperCommandStub(); + ret = StartServer(GRAPHIC_DUMPER_COMMAND_SA_ID, command); + if (ret) { + GDLOGI("Start graphic dumper command failed: %d\n", ret); + return ret; + } + return ret; +} + +GSError GraphicDumperServer::AddConfigListener(const std::string &tag, + sptr &listener) +{ + if (listener == nullptr) { + return GSERROR_INVALID_ARGUMENTS; + } + GDLOGFE("%{public}s", tag.c_str()); + + auto object = listener->AsObject(); + AddConfigDeathRecipient(object); + + if (HaveObject(object) == false) { + objectIdMap_[object] = ++objectId_; + configTagsMap_[objectId_].id = objectId_; + configTagsMap_[objectId_].listener = listener; + } + auto &objectId = objectIdMap_[object]; + auto &configTags = configTagsMap_[objectId]; + for (const auto &iter : configTags.tags) { + if (iter == tag) { + return GSERROR_OK; + } + } + configTags.tags.push_back(tag); + + for (auto &tag__ : configTags.tags) { + GDLOGFE("configTagsMap %{public}s", tag__.c_str()); + } + std::lock_guard lock(treeMutex_); + std::vector nodes = Split(tag, "."); + TreeNodePtr sub = root; + for (const auto& iter : nodes) { + sub = sub->GetSetNode(iter); + } + sub->AddListenerId(configTags.id); + + return GSERROR_OK; +} + +GSError GraphicDumperServer::RemoveConfigListener(sptr object) +{ + if (object == nullptr) { + return GSERROR_INVALID_ARGUMENTS; + } + auto &deathRecipient = configListenerDeathRecipientMap_[object]; + if (deathRecipient != nullptr) { + object->RemoveDeathRecipient(deathRecipient); + } + configListenerDeathRecipientMap_.erase(object); + + auto &objectId = objectIdMap_[object]; + auto &configTags = configTagsMap_[objectId]; + + for (auto &tag : configTags.tags) { + GDLOGFE("configTagsMap %{public}s", tag.c_str()); + std::lock_guard lock(treeMutex_); + std::vector nodes = Split(tag, "."); + TreeNodePtr sub = root; + RemoveNode(nodes, sub, configTags.id); + } + + object = nullptr; + return GSERROR_OK; +} + +GSError GraphicDumperServer::GetConfig(const std::string &k, std::string &v) +{ + GDLOGI("%{public}s -> %{public}s", k.c_str(), v.c_str()); + std::lock_guard lock(treeMutex_); + std::vector nodes = Split(k, "."); + TreeNodePtr sub = root; + for (const auto& iter : nodes) { + if (sub->HasNode(iter)) { + sub = sub->GetSetNode(iter); + } else { + return GSERROR_INVALID_ARGUMENTS; + } + } + v = sub->GetValue(); + GDLOGI("%{public}s -> %{public}s", k.c_str(), v.c_str()); + return GSERROR_OK; +} + +GSError GraphicDumperServer::SetConfig(const std::string &k, const std::string &v) +{ + GDLOGI("%{public}s -> %{public}s", k.c_str(), v.c_str()); + std::lock_guard lock(treeMutex_); + std::vector nodes = Split(k, "."); + TreeNodePtr sub = root; + for (const auto& iter : nodes) { + sub = sub->GetSetNode(iter); + } + if (sub->GetValue().compare(v)) { + sub->SetValue(v); + DispenseConfig(sub, k, v); + } + GDLOGI("%{public}s -> %{public}s", k.c_str(), v.c_str()); + return GSERROR_OK; +} + +GSError GraphicDumperServer::Dump(const std::string &tag) +{ + std::lock_guard lock(treeMutex_); + std::vector nodes = Split(tag, "."); + TreeNodePtr sub = root; + for (const auto& iter : nodes) { + if (iter.compare("--all") == 0) { + break; + } + GDLOGFE("%{public}s", iter.c_str()); + sub = sub->GetSetNode(iter); + } + DispenseDump(sub, tag); + GDLOGFE("%{public}s", tag.c_str()); + return GSERROR_OK; +} + +GSError GraphicDumperServer::AddInfoListener(sptr &listener) +{ + if (listener == nullptr) { + return GSERROR_INVALID_ARGUMENTS; + } + std::lock_guard guard(infoListenersMutex_); + auto object = listener->AsObject(); + AddInfoDeathRecipient(object); + infoListeners_[object] = listener; + return GSERROR_OK; +} + +GSError GraphicDumperServer::RemoveInfoListener(const wptr &object) +{ + std::lock_guard guard(infoListenersMutex_); + auto sObject = object.promote(); + if (infoListeners_.find(sObject) != infoListeners_.end()) { + infoListeners_.erase(sObject); + } + if (infoListeners_.empty()) { + logBuf_.sync = false; + logBuf_.mask.clear(); + } + return GSERROR_OK; +} + +GSError GraphicDumperServer::InfoHandle(const std::string &tag, const std::string &info) +{ + GDLOGFE("GraphicDumperServer::InfoHandle --start!!!!!!!!!"); + std::string logFlag = {"log."}; + GDLOGFE("%{public}s -> %{public}s", tag.c_str(), info.c_str()); + if (tag.compare(0, logFlag.size(), logFlag) == 0) { + GDLOGFE("InfoHandle to LogHandle"); + return LogHandle(tag.substr(logFlag.size()), info); + } + GDLOGFE("InfoHandle to SendToInfoListener"); + SendToInfoListener(tag + " : " + info); + return GSERROR_OK; +} +GSError GraphicDumperServer::GetLog(const std::string &tag, const std::string &info) +{ + GDLOGFE("%{public}s -> %{public}s", tag.c_str(), info.c_str()); + bool getAll = false; + if (tag.compare("--all") == 0) { + getAll = true; + logBuf_.mask.clear(); + } else { + logBuf_.mask = tag; + } + + { + std::lock_guard lock(logBlockVectorMutex_); + for (const auto& array : logBlockVector_) { + auto logBlock = reinterpret_cast(array.get()); + std::string toSendStr = {}; + uint32_t offset = 0; + GDLOGFE("logBlock->size = %{public}d", logBlock->size); + while (offset < logBlock->size) { + std::string str(reinterpret_cast(logBlock->data + offset)); + GDLOGFE("logBlock = %{public}s", str.c_str()); + StrLogRomveTag(getAll, tag, str, toSendStr); + offset += (str.size() + 1); + } + SendToInfoListener(toSendStr); + } + } + + std::string logStr = {}; + if (logBuf_.canSave || logBuf_.needSave) { + uint32_t index = (logBuf_.index + 1) % LOG_VEC_SIZE; + std::lock_guard guard(logBuf_.mutex[index]); + for (const auto& str : *logBuf_.vec[index]) { + GDLOGFE("logBuf_cansave = %{public}s", str.c_str()); + StrLogRomveTag(getAll, tag, str, logStr); + } + } + SendToInfoListener(logStr); + + logStr.clear(); + + { + uint32_t index = logBuf_.index; + std::lock_guard guard(logBuf_.mutex[index]); + for (const auto& str : *logBuf_.vec[index]) { + GDLOGFE("logBuf_ = %{public}s", str.c_str()); + StrLogRomveTag(getAll, tag, str, logStr); + } + } + SendToInfoListener(logStr); + + logBuf_.sync = true; + return GSERROR_OK; +} + +int32_t GraphicDumperServer::StartServer(int32_t systemAbility, sptr obj) +{ + if (systemAbility == 0 || obj == nullptr) { + GDLOGI("graphic dumper start_server parameter error"); + return 1; + } + + int result = 0; + while (1) { + auto sm = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (sm != nullptr) { + result = sm->AddSystemAbility(systemAbility, obj); + break; + } + GDLOGI("graphic dumper start_server SystemAbilityManager is nullptr"); + usleep(SLEEP_TIME); + } + return result; +} + +int32_t GraphicDumperServer::ReadDefaultConfig() +{ + int32_t successConst = 0; + int32_t failConst = 0; + std::string getLineStr = {}; + std::vector cfgStrs = {}; + std::ifstream input(GDUMPER_INI_PATH); + if (!input.is_open()) { + GDLOGE("failed to open: %{public}s", GDUMPER_INI_PATH); + } else { + while (!input.eof()) { + getline(input, getLineStr); + Trim(getLineStr); + std::string first = getLineStr.substr(0, 1); + if (first != "#" && first != "") { + cfgStrs.push_back(getLineStr); + } + } + input.clear(); + input.close(); + } + + std::lock_guard lock(treeMutex_); + for (auto iter : cfgStrs) { + if (!iter.empty()) { + std::vector cfg = Split(iter, "="); + if (cfg.size() != CFGTERMSIZE) { + failConst++; + GDLOGE("fail cfg(%{public}d): %{public}s", failConst, iter.c_str()); + } + std::vector nodes = Split(cfg[0], "."); + TreeNodePtr sub = root; + for (const auto& iter : nodes) { + sub = sub->GetSetNode(iter); + } + sub->SetValue(cfg[1]); + successConst++; + } + } + GDLOGI("There are %{public}d items successfully configured", successConst); + return failConst; +} + +void GraphicDumperServer::AddConfigDeathRecipient(sptr &object) +{ + if (!HaveConfigDeathRecipient(object)) { + sptr deathRecipient = new GraphicDumperClientListenerDeathRecipient(); + if ((object->IsProxyObject()) && (!object->AddDeathRecipient(deathRecipient))) { + GDLOGFE("Failed to add death recipient"); + } + configListenerDeathRecipientMap_[object] = deathRecipient; + } +} + +bool GraphicDumperServer::HaveConfigDeathRecipient(sptr &object) +{ + auto &map = configListenerDeathRecipientMap_; + return map.find(object) != map.end(); +} + +bool GraphicDumperServer::HaveObject(const sptr &obj) +{ + return objectIdMap_.find(obj) != objectIdMap_.end(); +} + +void GraphicDumperServer::VisitEach(const TreeNodePtr &node, TreeNodeVisitFunc func) +{ + GDLOGFI(""); + TreeNodeVisitFunc getV = [&](const TreeNodePtr &v) { + GDLOGFI(""); + func(v); + v->Foreach(getV); + }; + node->Foreach(getV); +} + +void GraphicDumperServer::RemoveNode(std::vector &vec, + TreeNodePtr &sub, + uint32_t &listenerId) +{ + GDLOGFE("listener: %{public}u", listenerId); + if (vec.empty() || sub == nullptr || listenerId == 0) { + return; + } + std::string tag = *vec.begin(); + GDLOGFE("tag: %{public}s", tag.c_str()); + vec.erase(vec.begin()); + + if (sub->HasNode(tag)) { + TreeNodePtr subNd = sub->GetSetNode(tag); + if (vec.empty()) { + subNd->RemoveListenerId(listenerId); + return; + } + RemoveNode(vec, subNd, listenerId); + if (subNd->IsEmptyNode()) { + sub->EraseNode(subNd->GetTag()); + } + } +} + +void GraphicDumperServer::DispenseConfig(const TreeNodePtr &node, const std::string &k, const std::string &v) +{ + GDLOGFI("%{public}s -> %{public}s", k.c_str(), v.c_str()); + auto dispenseConfig = [&](const TreeNodePtr &nd) { + GDLOGFI("%{public}s -> %{public}s", k.c_str(), v.c_str()); + auto ls = nd->GetListenerIds(); + for (const auto& id : ls) { + configTagsMap_[id].listener->OnConfigChange(k, v); + } + }; + dispenseConfig(node); + VisitEach(node, dispenseConfig); +} + +void GraphicDumperServer::DispenseDump(const TreeNodePtr &node, const std::string &tag) +{ + GDLOGFI("%{public}s", tag.c_str()); + auto dispenseDump = [&](const TreeNodePtr &nd) { + GDLOGFI("%{public}s", tag.c_str()); + auto ls = nd->GetListenerIds(); + for (const auto& id : ls) { + configTagsMap_[id].listener->OnDump(tag); + } + }; + dispenseDump(node); + VisitEach(node, dispenseDump); +} + +void GraphicDumperServer::AddInfoDeathRecipient(sptr &object) +{ + if (!HaveInfoDeathRecipient(object)) { + sptr deathRecipient = new GraphicDumperInfoListenerDeathRecipient(); + if ((object->IsProxyObject()) && (!object->AddDeathRecipient(deathRecipient))) { + GDLOGFE("Failed to add death recipient"); + } + infoListenerDeathRecipientMap_[object] = deathRecipient; + } +} + +bool GraphicDumperServer::HaveInfoDeathRecipient(sptr &object) +{ + auto &map = infoListenerDeathRecipientMap_; + return map.find(object) != map.end(); +} + +void GraphicDumperServer::SendToInfoListener(const std::string &info) +{ + std::lock_guard guard(infoListenersMutex_); + for (const auto& [k, v] : infoListeners_) { + v->OnInfoComing(info); + } +} + +void GraphicDumperServer::SaveLog(std::any server) +{ + auto serverPtr = std::any_cast(server); + uint32_t index = (serverPtr->logBuf_.index + 1) % LOG_VEC_SIZE; + std::lock_guard guard(serverPtr->logBuf_.mutex[index]); + + uint32_t size = sizeof(LogBlock) + serverPtr->logBuf_.size[index] + 1; + auto logArray = std::make_unique(size); + auto logBlock = reinterpret_cast(logArray.get()); + logBlock->size = serverPtr->logBuf_.size[index]; + logBlock->length = serverPtr->logBuf_.size[index]; + uint32_t offset = 0; + for (const auto& str : *serverPtr->logBuf_.vec[index]) { + int ret = memcpy_s(logBlock->data + offset, + serverPtr->logBuf_.size[index] - offset, + str.c_str(), str.size() + 1); + if (ret < 0) { + return; + } + offset += str.size() + 1; + } + std::lock_guard lock(serverPtr->logBlockVectorMutex_); + if ((serverPtr->logBlockSize_ + serverPtr->logBuf_.size[index]) > LOG_BLOCK_SIZE_MAX) { + auto logFirstBlock = reinterpret_cast(serverPtr->logBlockVector_.begin()->get()); + serverPtr->logBlockSize_ -= logFirstBlock->size; + serverPtr->logBlockVector_.erase(serverPtr->logBlockVector_.begin()); + } + serverPtr->logBlockVector_.push_back(std::move(logArray)); + serverPtr->logBlockSize_ += serverPtr->logBuf_.size[index]; + serverPtr->logBuf_.vec[index]->clear(); + serverPtr->logBuf_.size[index] = 0; +} + +GSError GraphicDumperServer::LogHandle(const std::string &tag, const std::string &info) +{ + std::string log = tag + " | " + info; + GDLOGFI("%{public}s -> %{public}s", tag.c_str(), info.c_str()); + { + std::lock_guard guard(logBuf_.mutex[logBuf_.index]); + logBuf_.size[logBuf_.index] += log.size() + 1; + logBuf_.vec[logBuf_.index]->push_back(log); + if (logBuf_.canSave && (logBuf_.size[logBuf_.index] > (LOG_BUF_SIZE_MAX / LOG_VEC_SIZE))) { + thread_ = std::make_unique(&GraphicDumperServer::SaveLog, this); + logBuf_.needSave = true; + logBuf_.canSave = false; + } + if (logBuf_.size[logBuf_.index] >= LOG_BUF_SIZE_MAX) { + logBuf_.vec[logBuf_.index]->shrink_to_fit(); + if (logBuf_.needSave) { + thread_->join(); + logBuf_.needSave = false; + } + logBuf_.index = (logBuf_.index + 1) % LOG_VEC_SIZE; + logBuf_.canSave = true; + } + } + if (logBuf_.sync) { + if ((!logBuf_.mask.empty()) && (log.compare(0, logBuf_.mask.size(), logBuf_.mask) != 0)) { + return GSERROR_OK; + } + auto pos = log.find_first_of("| ["); + constexpr int offset = 2; + if (pos == std::string::npos) { + pos = 0; + } else { + pos += offset; + } + SendToInfoListener(log.substr(pos)); + } + return GSERROR_OK; +} +} // namespace OHOS diff --git a/frameworks/dumper/src/graphic_dumper_server_main.cpp b/frameworks/dumper/src/graphic_dumper_server_main.cpp new file mode 100644 index 0000000000..f768b62f18 --- /dev/null +++ b/frameworks/dumper/src/graphic_dumper_server_main.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021 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 "graphic_dumper_server.h" + +using namespace OHOS; + +int main() +{ + int ret = GraphicDumperServer::GetInstance()->Init(); + if (ret == 0) { + IPCSkeleton::JoinWorkThread(); + } + return ret; +} diff --git a/frameworks/dumper/src/graphic_dumper_tree.cpp b/frameworks/dumper/src/graphic_dumper_tree.cpp new file mode 100644 index 0000000000..e65eabd58d --- /dev/null +++ b/frameworks/dumper/src/graphic_dumper_tree.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2021 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 "graphic_dumper_tree.h" + +#include "graphic_dumper_hilog.h" + +namespace OHOS { +namespace { +constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0, "GraphicDumperTree" }; +} // namespace + +TreeNodePtr GraphicDumperTree::GetSetNode(const std::string s) +{ + if (nodeMap_ == nullptr) { + nodeMap_ = std::make_unique(); + } + if (!HasNode(s)) { + (*nodeMap_)[s] = std::make_shared(); + (*nodeMap_)[s]->tag_ = s; + } + return (*nodeMap_)[s]; +} + +bool GraphicDumperTree::HasNode(const std::string s) +{ + return nodeMap_->find(s) != nodeMap_->end(); +} + +bool GraphicDumperTree::IsEmptyNode() +{ + if (nodeMap_->empty() && listenerIds_.empty()) { + return true; + } + return false; +} + +void GraphicDumperTree::EraseNode(const std::string &s) +{ + (*nodeMap_)[s] = nullptr; + nodeMap_->erase(s); +} + +std::string GraphicDumperTree::GetTag() +{ + return tag_; +} + +void GraphicDumperTree::SetValue(const std::string s) +{ + value_ = s; +} + +std::string GraphicDumperTree::GetValue() +{ + return value_; +} + +void GraphicDumperTree::AddListenerId(uint32_t &listenerId) +{ + GDLOGFI(""); + listenerIds_.push_back(listenerId); +} + +void GraphicDumperTree::RemoveListenerId(uint32_t &listenerId) +{ + GDLOGFI("%{public}u", listenerId); + for (auto iter = listenerIds_.begin(); iter != listenerIds_.end(); ++iter) { + GDLOGFI("%{public}u <==> %{public}u", (*iter), listenerId); + if (*iter == listenerId) { + GDLOGFI(""); + listenerIds_.erase(iter--); + } + } +} + +std::vector GraphicDumperTree::GetListenerIds() const +{ + GDLOGFI(""); + return listenerIds_; +} + +void GraphicDumperTree::Foreach(TreeNodeVisitFunc func) const +{ + GDLOGFI(""); + if (nodeMap_ == nullptr) { + return; + } + for (const auto& [k, v] : (*nodeMap_)) { + GDLOGFI("%{public}s", k.c_str()); + func(v); + } +} +} // namespace OHOS diff --git a/frameworks/dumper/src/graphic_dumper_util.cpp b/frameworks/dumper/src/graphic_dumper_util.cpp new file mode 100644 index 0000000000..6eb36cb4cb --- /dev/null +++ b/frameworks/dumper/src/graphic_dumper_util.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 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 "graphic_dumper_util.h" + +namespace OHOS { +std::vector Split(std::string src, const std::string &splitStr) +{ + std::vector ret; + std::string::size_type pos = 0; + while (pos != std::string::npos) { + pos = src.find(splitStr); + if (pos == std::string::npos) { + if (!src.empty()) { + ret.push_back(src); + } + } else { + if (!src.empty()) { + ret.push_back(src.substr(0, pos)); + } + src = src.substr(pos + splitStr.size()); + } + } + return ret; +} +} // namespace OHOS diff --git a/frameworks/dumper/src/ipc/graphic_dumper_client_listener_death_recipient.cpp b/frameworks/dumper/src/ipc/graphic_dumper_client_listener_death_recipient.cpp new file mode 100644 index 0000000000..0d6117d705 --- /dev/null +++ b/frameworks/dumper/src/ipc/graphic_dumper_client_listener_death_recipient.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 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 "ipc/graphic_dumper_client_listener_death_recipient.h" + +#include "graphic_dumper_server.h" + +namespace OHOS { +void GraphicDumperClientListenerDeathRecipient::OnRemoteDied(const wptr &object) +{ + if (object == nullptr) { + return; + } + GraphicDumperServer::GetInstance()->RemoveConfigListener(object.promote()); +} +} // namespace OHOS diff --git a/frameworks/dumper/src/ipc/graphic_dumper_client_listener_proxy.cpp b/frameworks/dumper/src/ipc/graphic_dumper_client_listener_proxy.cpp new file mode 100644 index 0000000000..0313d85a9c --- /dev/null +++ b/frameworks/dumper/src/ipc/graphic_dumper_client_listener_proxy.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 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 "ipc/graphic_dumper_client_listener_proxy.h" + +#include +#include + +#include "graphic_dumper_hilog.h" +#include "graphic_common.h" + +namespace OHOS { +namespace { +constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0, "GraphicDumperClientListenerProxy" }; +} + +GraphicDumperClientListenerProxy::GraphicDumperClientListenerProxy(const sptr& impl) + : IRemoteProxy(impl) +{ +} + +void GraphicDumperClientListenerProxy::OnConfigChange(const std::string &tag, const std::string &val) +{ + MessageOption opt; + MessageParcel arg; + MessageParcel ret; + GDLOGFI("%{public}s -> %{public}s", tag.c_str(), val.c_str()); + + if (!arg.WriteInterfaceToken(GetDescriptor())) { + GDLOGE("write interface token failed"); + } + + arg.WriteString(tag); + arg.WriteString(val); + int result = Remote()->SendRequest(IGRAPHIC_DUMPER_CLIENT_LISTENER_ON_CONFIG_CHANGE, arg, ret, opt); + if (result) { + GDLOG_ERROR_API(result, SendRequest); + return; + } + return; +} + +void GraphicDumperClientListenerProxy::OnDump(const std::string &tag) +{ + MessageOption opt; + MessageParcel arg; + MessageParcel ret; + GDLOGFI("%{public}s", tag.c_str()); + + if (!arg.WriteInterfaceToken(GetDescriptor())) { + GDLOGE("write interface token failed"); + } + + arg.WriteString(tag); + int result = Remote()->SendRequest(IGRAPHIC_DUMPER_CLIENT_LISTENER_ON_DUMP, arg, ret, opt); + if (result) { + GDLOG_ERROR_API(result, SendRequest); + return; + } + return; +} +} // namespace OHOS diff --git a/frameworks/dumper/src/ipc/graphic_dumper_client_listener_stub.cpp b/frameworks/dumper/src/ipc/graphic_dumper_client_listener_stub.cpp new file mode 100644 index 0000000000..979899f9cd --- /dev/null +++ b/frameworks/dumper/src/ipc/graphic_dumper_client_listener_stub.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 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 "ipc/graphic_dumper_client_listener_stub.h" + +#include "graphic_dumper_hilog.h" +#include "graphic_common.h" + +namespace OHOS { +namespace { +constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0, "GraphicDumperClientListenerStub" }; +} + +int32_t GraphicDumperClientListenerStub::OnRemoteRequest(uint32_t code, MessageParcel& data, + MessageParcel& reply, MessageOption& option) +{ + auto remoteDescriptor = data.ReadInterfaceToken(); + if (GetDescriptor() != remoteDescriptor) { + return 1; + } + + switch (code) { + case IGRAPHIC_DUMPER_CLIENT_LISTENER_ON_CONFIG_CHANGE: { + std::string tag = data.ReadString(); + std::string val = data.ReadString(); + GDLOGI("%{public}s -> %{public}s", tag.c_str(), val.c_str()); + OnConfigChange(tag, val); + reply.WriteInt32(GSERROR_OK); + } + break; + case IGRAPHIC_DUMPER_CLIENT_LISTENER_ON_DUMP: { + std::string val = data.ReadString(); + OnDump(val); + reply.WriteInt32(GSERROR_OK); + } + break; + default: + GDLOGFE("code %{public}d cannot process", code); + return 1; + break; + } + return 0; +} +} // namespace OHOS diff --git a/frameworks/dumper/src/ipc/graphic_dumper_command_proxy.cpp b/frameworks/dumper/src/ipc/graphic_dumper_command_proxy.cpp new file mode 100644 index 0000000000..52a952720d --- /dev/null +++ b/frameworks/dumper/src/ipc/graphic_dumper_command_proxy.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2021 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 "ipc/graphic_dumper_command_proxy.h" + +#include +#include + +#include "graphic_dumper_hilog.h" + +namespace OHOS { +namespace { +constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0, "GraphicDumperCommandProxy" }; +} + +GraphicDumperCommandProxy::GraphicDumperCommandProxy(const sptr& impl) + : IRemoteProxy(impl) +{ +} + +GSError GraphicDumperCommandProxy::GetConfig(const std::string &k, std::string &v) +{ + MessageOption opt; + MessageParcel arg; + MessageParcel ret; + GDLOGFE("%{public}s -> %{public}s", k.c_str(), v.c_str()); + + if (!arg.WriteInterfaceToken(GetDescriptor())) { + GDLOGE("write interface token failed"); + } + + arg.WriteString(k); + arg.WriteString(v); + int result = Remote()->SendRequest(IGRAPHIC_DUMPER_COMMAND_GET_CONFIG, arg, ret, opt); + if (result) { + GDLOG_ERROR_API(result, SendRequest); + return GSERROR_API_FAILED; + } + GSError retCode = static_cast(ret.ReadInt32()); + if (retCode == GSERROR_OK) { + v = ret.ReadString(); + GDLOGFE("%{public}s -> %{public}s", k.c_str(), v.c_str()); + } + return retCode; +} + +GSError GraphicDumperCommandProxy::SetConfig(const std::string &k, const std::string &v) +{ + MessageOption opt; + MessageParcel arg; + MessageParcel ret; + GDLOGFE("%{public}s -> %{public}s", k.c_str(), v.c_str()); + + if (!arg.WriteInterfaceToken(GetDescriptor())) { + GDLOGE("write interface token failed"); + } + + arg.WriteString(k); + arg.WriteString(v); + int result = Remote()->SendRequest(IGRAPHIC_DUMPER_COMMAND_SET_CONFIG, arg, ret, opt); + if (result) { + GDLOG_ERROR_API(result, SendRequest); + return GSERROR_API_FAILED; + } + return GSERROR_OK; +} + +GSError GraphicDumperCommandProxy::Dump(const std::string &tag) +{ + MessageOption opt; + MessageParcel arg; + MessageParcel ret; + GDLOGFE("%{public}s", tag.c_str()); + + if (!arg.WriteInterfaceToken(GetDescriptor())) { + GDLOGE("write interface token failed"); + } + + arg.WriteString(tag); + int result = Remote()->SendRequest(IGRAPHIC_DUMPER_COMMAND_DUMP, arg, ret, opt); + if (result) { + GDLOG_ERROR_API(result, SendRequest); + return GSERROR_API_FAILED; + } + return GSERROR_OK; +} + +GSError GraphicDumperCommandProxy::GetLog(const std::string &tag, std::string &log) +{ + MessageOption opt; + MessageParcel arg; + MessageParcel ret; + GDLOGFE("%{public}s -> %{public}s", tag.c_str(), log.c_str()); + + if (!arg.WriteInterfaceToken(GetDescriptor())) { + GDLOGE("write interface token failed"); + } + + arg.WriteString(tag); + int result = Remote()->SendRequest(IGRAPHIC_DUMPER_COMMAND_GET_LOG, arg, ret, opt); + if (result) { + GDLOG_ERROR_API(result, SendRequest); + return GSERROR_API_FAILED; + } + return GSERROR_OK; +} + +GSError GraphicDumperCommandProxy::AddInfoListener(const std::string &tag, sptr &listener) +{ + if (listener == nullptr) { + GDLOG_FAILURE_NO(GSERROR_INVALID_ARGUMENTS); + return GSERROR_INVALID_ARGUMENTS; + } + MessageOption opt; + MessageParcel arg; + MessageParcel ret; + + if (!arg.WriteInterfaceToken(GetDescriptor())) { + GDLOGE("write interface token failed"); + } + arg.WriteString(tag); + arg.WriteRemoteObject(listener->AsObject()); + + int result = Remote()->SendRequest(IGRAPHIC_DUMPER_COMMAND_ADD_INFO_LISTENER, arg, ret, opt); + if (result) { + GDLOG_ERROR_API(result, SendRequest); + return GSERROR_BINDER; + } + + GSError err = (GSError)ret.ReadInt32(); + if (err != GSERROR_OK) { + GDLOG_FAILURE_NO(err); + } + return err; +} +} // namespace OHOS diff --git a/frameworks/dumper/src/ipc/graphic_dumper_command_stub.cpp b/frameworks/dumper/src/ipc/graphic_dumper_command_stub.cpp new file mode 100644 index 0000000000..8b55c283b8 --- /dev/null +++ b/frameworks/dumper/src/ipc/graphic_dumper_command_stub.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021 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 "ipc/graphic_dumper_command_stub.h" + +#include "graphic_dumper_hilog.h" +#include "graphic_dumper_server.h" +#include "ipc/igraphic_dumper_command.h" + +namespace OHOS { +namespace { +constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0, "GraphicDumperCommandStub" }; +} + +int32_t GraphicDumperCommandStub::OnRemoteRequest(uint32_t code, MessageParcel& data, + MessageParcel& reply, MessageOption& option) +{ + auto remoteDescriptor = data.ReadInterfaceToken(); + if (GetDescriptor() != remoteDescriptor) { + return 1; + } + switch (code) { + case IGRAPHIC_DUMPER_COMMAND_GET_CONFIG: { + std::string k = data.ReadString(); + std::string v = data.ReadString(); + GSError ret = GetConfig(k, v); + reply.WriteInt32(ret); + reply.WriteString(v); + break; + } + + case IGRAPHIC_DUMPER_COMMAND_SET_CONFIG: { + std::string k = data.ReadString(); + std::string v = data.ReadString(); + GSError ret = SetConfig(k, v); + reply.WriteInt32(ret); + break; + } + + case IGRAPHIC_DUMPER_COMMAND_DUMP: { + std::string v = data.ReadString(); + GSError ret = Dump(v); + reply.WriteInt32(ret); + break; + } + + case IGRAPHIC_DUMPER_COMMAND_GET_LOG: { + std::string tag = data.ReadString(); + std::string log = ""; + GSError ret = GetLog(tag, log); + reply.WriteInt32(ret); + break; + } + case IGRAPHIC_DUMPER_COMMAND_ADD_INFO_LISTENER: { + auto tag = data.ReadString(); + auto remoteObject = data.ReadRemoteObject(); + if (remoteObject == nullptr) { + reply.WriteInt32(GSERROR_INVALID_ARGUMENTS); + GDLOG_FAILURE_NO(GSERROR_INVALID_ARGUMENTS); + break; + } + + auto l = iface_cast(remoteObject); + GSError ret = AddInfoListener(tag, l); + reply.WriteInt32(ret); + if (ret != GSERROR_OK) { + GDLOG_FAILURE_NO(ret); + } + break; + } + default: { + return 1; + break; + } + } + return 0; +} + +GSError GraphicDumperCommandStub::GetConfig(const std::string &k, std::string &v) +{ + GDLOGFE("%{public}s -> %{public}s", k.c_str(), v.c_str()); + GraphicDumperServer::GetInstance()->GetConfig(k, v); + GDLOGFE("%{public}s -> %{public}s", k.c_str(), v.c_str()); + return GSERROR_OK; +} + +GSError GraphicDumperCommandStub::SetConfig(const std::string &k, const std::string &v) +{ + GDLOGFE("%{public}s -> %{public}s", k.c_str(), v.c_str()); + GraphicDumperServer::GetInstance()->SetConfig(k, v); + return GSERROR_OK; +} + +GSError GraphicDumperCommandStub::Dump(const std::string &tag) +{ + GDLOGFE("%{public}s", tag.c_str()); + GraphicDumperServer::GetInstance()->Dump(tag); + return GSERROR_OK; +} + +GSError GraphicDumperCommandStub::GetLog(const std::string &tag, std::string &log) +{ + GDLOGFE("%{public}s -> %{public}s", tag.c_str(), log.c_str()); + GraphicDumperServer::GetInstance()->GetLog(tag, log); + return GSERROR_OK; +} + +GSError GraphicDumperCommandStub::AddInfoListener(const std::string &tag, sptr &listener) +{ + GDLOGFE(""); + if (listener == nullptr) { + return GSERROR_INVALID_ARGUMENTS; + } + return GraphicDumperServer::GetInstance()->AddInfoListener(listener); +} +} // namespace OHOS diff --git a/frameworks/dumper/src/ipc/graphic_dumper_info_listener_death_recipient.cpp b/frameworks/dumper/src/ipc/graphic_dumper_info_listener_death_recipient.cpp new file mode 100644 index 0000000000..a6b973e728 --- /dev/null +++ b/frameworks/dumper/src/ipc/graphic_dumper_info_listener_death_recipient.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021 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 "ipc/graphic_dumper_info_listener_death_recipient.h" +#include "graphic_dumper_server.h" +#include "ipc/igraphic_dumper_command.h" +#include "graphic_common.h" +#include "graphic_dumper_hilog.h" +namespace OHOS { +void GraphicDumperInfoListenerDeathRecipient::OnRemoteDied(const wptr &object) +{ + if (object == nullptr) { + return; + } + GraphicDumperServer::GetInstance()->RemoveInfoListener(object); +} +} // namespace OHOS diff --git a/frameworks/dumper/src/ipc/graphic_dumper_info_listener_proxy.cpp b/frameworks/dumper/src/ipc/graphic_dumper_info_listener_proxy.cpp new file mode 100644 index 0000000000..efad0f22ef --- /dev/null +++ b/frameworks/dumper/src/ipc/graphic_dumper_info_listener_proxy.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 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 "ipc/graphic_dumper_info_listener_proxy.h" + +#include +#include + +#include "graphic_dumper_hilog.h" + +namespace OHOS { +namespace { +constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0, "GraphicDumperInfoListenerProxy" }; +} + +GraphicDumperInfoListenerProxy::GraphicDumperInfoListenerProxy(const sptr& impl) + : IRemoteProxy(impl) +{ +} + +void GraphicDumperInfoListenerProxy::OnInfoComing(const std::string &info) +{ + MessageOption opt; + MessageParcel arg; + MessageParcel ret; + if (!arg.WriteInterfaceToken(GetDescriptor())) { + GDLOGE("write interface token failed"); + } + + arg.WriteString(info); + int result = Remote()->SendRequest(IGRAPHIC_DUMPER_INFO_LISTENER_ON_INFO_COMING, arg, ret, opt); + if (result) { + GDLOG_ERROR_API(result, SendRequest); + return; + } + return; +} +} // namespace OHOS diff --git a/frameworks/dumper/src/ipc/graphic_dumper_info_listener_stub.cpp b/frameworks/dumper/src/ipc/graphic_dumper_info_listener_stub.cpp new file mode 100644 index 0000000000..b01ce6e9b4 --- /dev/null +++ b/frameworks/dumper/src/ipc/graphic_dumper_info_listener_stub.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 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 "ipc/graphic_dumper_info_listener_stub.h" + +#include "graphic_dumper_hilog.h" +#include "graphic_common.h" + +namespace OHOS { +namespace { +constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0, "GraphicDumperInfoListenerStub" }; +} + +int32_t GraphicDumperInfoListenerStub::OnRemoteRequest(uint32_t code, MessageParcel& data, + MessageParcel& reply, MessageOption& option) +{ + auto remoteDescriptor = data.ReadInterfaceToken(); + if (GetDescriptor() != remoteDescriptor) { + return 1; + } + + switch (code) { + case IGRAPHIC_DUMPER_INFO_LISTENER_ON_INFO_COMING: { + std::string info = data.ReadString(); + OnInfoComing(info); + reply.WriteInt32(GSERROR_OK); + break; + } + + default: { + GDLOGFE("code %{public}d cannot process", code); + return 1; + break; + } + } + return 0; +} +} // namespace OHOS diff --git a/frameworks/dumper/src/ipc/graphic_dumper_service_proxy.cpp b/frameworks/dumper/src/ipc/graphic_dumper_service_proxy.cpp new file mode 100644 index 0000000000..ad556de2cd --- /dev/null +++ b/frameworks/dumper/src/ipc/graphic_dumper_service_proxy.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 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 "ipc/graphic_dumper_service_proxy.h" + +#include +#include + +#include "graphic_dumper_hilog.h" + + +namespace OHOS { +namespace { +constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0, "GraphicDumperServiceProxy" }; +} + +GraphicDumperServiceProxy::GraphicDumperServiceProxy(const sptr& impl) + : IRemoteProxy(impl) +{ +} + +GSError GraphicDumperServiceProxy::AddClientListener(const std::string &tag, + sptr &listener) +{ + if (listener == nullptr) { + GDLOG_FAILURE_NO(GSERROR_INVALID_ARGUMENTS); + return GSERROR_INVALID_ARGUMENTS; + } + MessageOption opt; + MessageParcel arg; + MessageParcel ret; + + if (!arg.WriteInterfaceToken(GetDescriptor())) { + GDLOGE("write interface token failed"); + } + arg.WriteString(tag); + arg.WriteRemoteObject(listener->AsObject()); + + int result = Remote()->SendRequest(IGRAPHIC_DUMPER_SERVICE_ADD_CLIENT_LISTENER, arg, ret, opt); + if (result) { + GDLOG_ERROR_API(result, SendRequest); + return GSERROR_BINDER; + } + + GSError err = (GSError)ret.ReadInt32(); + if (err != GSERROR_OK) { + GDLOG_FAILURE_NO(err); + } + + return err; +} + +GSError GraphicDumperServiceProxy::SendInfo(const std::string &tag, const std::string &info) +{ + MessageOption opt; + MessageParcel arg; + MessageParcel ret; + + if (!arg.WriteInterfaceToken(GetDescriptor())) { + GDLOGE("write interface token failed"); + } + arg.WriteString(tag); + arg.WriteString(info); + GDLOGE("SendInfo SendRequest !!!!!"); + int result = Remote()->SendRequest(IGRAPHIC_DUMPER_SERVICE_SEND_INFO, arg, ret, opt); + if (result) { + GDLOG_ERROR_API(result, SendRequest); + return GSERROR_BINDER; + } + return GSERROR_OK; +} +} // namespace OHOS diff --git a/frameworks/dumper/src/ipc/graphic_dumper_service_stub.cpp b/frameworks/dumper/src/ipc/graphic_dumper_service_stub.cpp new file mode 100644 index 0000000000..a20185a813 --- /dev/null +++ b/frameworks/dumper/src/ipc/graphic_dumper_service_stub.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2021 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 "ipc/graphic_dumper_service_stub.h" + +#include "graphic_dumper_hilog.h" +#include "graphic_dumper_server.h" + +#define REMOTE_RETURN(reply, gs_error) \ + do { \ + (reply).WriteInt32(gs_error); \ + if ((gs_error) != GSERROR_OK) { \ + GDLOG_FAILURE_NO(gs_error); \ + } \ + } while (0); \ + break + +namespace OHOS { +namespace { +constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0, "GraphicDumperServiceStub" }; +} + +int32_t GraphicDumperServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, + MessageParcel &reply, MessageOption &option) +{ + auto remoteDescriptor = data.ReadInterfaceToken(); + if (GetDescriptor() != remoteDescriptor) { + return 1; + } + + switch (code) { + case IGRAPHIC_DUMPER_SERVICE_ADD_CLIENT_LISTENER: { + auto tag = data.ReadString(); + GDLOGFE("%{public}s", tag.c_str()); + auto remoteObject = data.ReadRemoteObject(); + if (remoteObject == nullptr) { + reply.WriteInt32(GSERROR_INVALID_ARGUMENTS); + GDLOG_FAILURE_NO(GSERROR_INVALID_ARGUMENTS); + break; + } + auto l = iface_cast(remoteObject); + GSError ret = AddClientListener(tag, l); + reply.WriteInt32(ret); + if (ret != GSERROR_OK) { + GDLOG_FAILURE_NO(ret); + } + break; + } + case IGRAPHIC_DUMPER_SERVICE_SEND_INFO: { + std::string tag = data.ReadString(); + std::string info = data.ReadString(); + GSError ret = SendInfo(tag, info); + reply.WriteInt32(ret); + if (ret != GSERROR_OK) { + GDLOG_FAILURE_NO(ret); + } + break; + } + default: { + GDLOGFE("code %{public}d cannot process", code); + return 1; + break; + } + } + return 0; +} +GSError GraphicDumperServiceStub::AddClientListener(const std::string &tag, + sptr &listener) +{ + if (listener == nullptr) { + return GSERROR_INVALID_ARGUMENTS; + } + return GraphicDumperServer::GetInstance()->AddConfigListener(tag, listener); +} +GSError GraphicDumperServiceStub::SendInfo(const std::string &tag, const std::string &info) +{ + return GraphicDumperServer::GetInstance()->InfoHandle(tag, info); +} +} // namespace OHOS diff --git a/frameworks/wm/BUILD.gn b/frameworks/wm/BUILD.gn index e78980b52d..baf2554f15 100644 --- a/frameworks/wm/BUILD.gn +++ b/frameworks/wm/BUILD.gn @@ -148,6 +148,8 @@ ohos_shared_library("libwmclient") { "src/subwindow_option_impl.cpp", "src/subwindow_video_impl.cpp", "src/tester.cpp", + "src/virtual_display_option.cpp", + "src/virtual_display_option_impl.cpp", "src/wayland_service.cpp", "src/window_attribute.cpp", "src/window_impl.cpp", diff --git a/frameworks/wm/include/input_listener_manager.h b/frameworks/wm/include/input_listener_manager.h index b694e5cdd5..a21a3b1636 100644 --- a/frameworks/wm/include/input_listener_manager.h +++ b/frameworks/wm/include/input_listener_manager.h @@ -68,6 +68,13 @@ private: void *window; }; +struct Seat { + struct wl_seat *seat; + struct wl_pointer *pointer; + struct wl_keyboard *keyboard; + struct wl_touch *touch; +}; + using InputListeners = std::vector>; class InputListenerManager : public RefBase { @@ -95,16 +102,13 @@ private: static inline SingletonDelegator delegator; static void OnAppear(const GetServiceFunc get, const std::string &iname, uint32_t ver); - static inline struct wl_seat *seat = nullptr; + static inline std::vector seats; + static uint32_t FindSeatNum(struct wl_seat *seat); - static void SeatHandleCapabilities(void *, struct wl_seat *, uint32_t caps); - static void RegisterPointerListener(uint32_t caps); - static void RegisterKeyboardListener(uint32_t caps); - static void RegisterTouchListener(uint32_t caps); - - static inline struct wl_pointer *pointer = nullptr; - static inline struct wl_keyboard *keyboard = nullptr; - static inline struct wl_touch *touch = nullptr; + static inline void SeatHandleCapabilities(void *, struct wl_seat *, uint32_t caps); + static inline void RegisterPointerListener(uint32_t caps, struct wl_seat *seat); + static inline void RegisterKeyboardListener(uint32_t caps, struct wl_seat *seat); + static inline void RegisterTouchListener(uint32_t caps, struct wl_seat *seat); }; } // namespace OHOS diff --git a/frameworks/wm/include/virtual_display_option_impl.h b/frameworks/wm/include/virtual_display_option_impl.h new file mode 100644 index 0000000000..7c5fc49459 --- /dev/null +++ b/frameworks/wm/include/virtual_display_option_impl.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_WM_INCLUDE_VIRTUAL_DISPLAY_OPTION_IMPL_H +#define FRAMEWORKS_WM_INCLUDE_VIRTUAL_DISPLAY_OPTION_IMPL_H + +#include + +namespace OHOS { +class VirtualDisplayOptionImpl : public VirtualDisplayOption { +public: + VirtualDisplayOptionImpl() = default; + virtual ~VirtualDisplayOptionImpl() = default; + + virtual WMError SetX(int32_t x) override; + virtual WMError SetY(int32_t y) override; + virtual WMError SetWidth(uint32_t width) override; + virtual WMError SetHeight(uint32_t height) override; + + virtual int32_t GetX() const override; + virtual int32_t GetY() const override; + virtual uint32_t GetWidth() const override; + virtual uint32_t GetHeight() const override; + + virtual bool IsSettingX() const override; + virtual bool IsSettingY() const override; + virtual bool IsSettingWidth() const override; + virtual bool IsSettingHeight() const override; + +private: + bool settingX = false; + bool settingY = false; + bool settingWidth = false; + bool settingHeight = false; + + int32_t x = 0; + int32_t y = 0; + uint32_t width = 1; + uint32_t height = 1; +}; +} // namespace OHOS + +#endif // FRAMEWORKS_WM_INCLUDE_VIRTUAL_DISPLAY_OPTION_IMPL_H diff --git a/frameworks/wm/include/window_manager_impl.h b/frameworks/wm/include/window_manager_impl.h index c22631ad90..9a0ed2334f 100644 --- a/frameworks/wm/include/window_manager_impl.h +++ b/frameworks/wm/include/window_manager_impl.h @@ -52,6 +52,10 @@ public: virtual WMError ListenNextScreenShot(int32_t id, IScreenShotCallback *cb) override; virtual WMError ListenNextWindowShot(const sptr &window, IWindowShotCallback *cb) override; + virtual WMError CreateVirtualDisplay(const sptr &option) override; + virtual WMError DestroyVirtualDisplay(uint32_t did) override; + virtual WMError SetDisplayMode(WMSDisplayMode mode) override; + private: WindowManagerImpl(); virtual ~WindowManagerImpl() override; diff --git a/frameworks/wm/src/input_listener_manager.cpp b/frameworks/wm/src/input_listener_manager.cpp index 97f1880b6e..8cde4a56e1 100644 --- a/frameworks/wm/src/input_listener_manager.cpp +++ b/frameworks/wm/src/input_listener_manager.cpp @@ -42,24 +42,27 @@ void InputListenerManager::Init() void InputListenerManager::Deinit() { - if (seat != nullptr) { - wl_seat_destroy(seat); - seat = nullptr; - } + while (!seats.empty()) { + if (seats.back().seat != nullptr) { + wl_seat_destroy(seats.back().seat); + seats.back().seat = nullptr; + } - if (pointer != nullptr) { - wl_pointer_destroy(pointer); - pointer = nullptr; - } + if (seats.back().pointer != nullptr) { + wl_pointer_destroy(seats.back().pointer); + seats.back().pointer = nullptr; + } - if (keyboard != nullptr) { - wl_keyboard_destroy(keyboard); - keyboard = nullptr; - } + if (seats.back().keyboard != nullptr) { + wl_keyboard_destroy(seats.back().keyboard); + seats.back().keyboard = nullptr; + } - if (touch != nullptr) { - wl_touch_destroy(touch); - touch = nullptr; + if (seats.back().touch != nullptr) { + wl_touch_destroy(seats.back().touch); + seats.back().touch = nullptr; + } + seats.pop_back(); } g_getFocus = []() { return InputListeners(); }; @@ -138,21 +141,25 @@ void InputListenerManager::OnAppear(const GetServiceFunc get, const std::string { if (iname == "wl_seat") { constexpr uint32_t wlSeatVersion = 1; - seat = static_cast(get(&wl_seat_interface, wlSeatVersion)); - if (seat == nullptr) { + struct wl_seat *s = static_cast(get(&wl_seat_interface, wlSeatVersion)); + if (s == nullptr) { return; } + Seat seat = { + .seat = s, + }; + seats.push_back(seat); static struct wl_seat_listener listener = { SeatHandleCapabilities }; - wl_seat_add_listener(seat, &listener, nullptr); + wl_seat_add_listener(s, &listener, nullptr); } } -void InputListenerManager::SeatHandleCapabilities(void *, struct wl_seat *, uint32_t caps) +void InputListenerManager::SeatHandleCapabilities(void *, struct wl_seat * seat, uint32_t caps) { - InputListenerManager::RegisterPointerListener(caps); - InputListenerManager::RegisterKeyboardListener(caps); - InputListenerManager::RegisterTouchListener(caps); + InputListenerManager::RegisterPointerListener(caps, seat); + InputListenerManager::RegisterKeyboardListener(caps, seat); + InputListenerManager::RegisterTouchListener(caps, seat); } namespace { @@ -448,8 +455,23 @@ void OnTouchOrientation(void *, struct wl_touch *, } } // namespace -void InputListenerManager::RegisterPointerListener(uint32_t caps) +uint32_t InputListenerManager::FindSeatNum(struct wl_seat *seat) { + uint32_t num = 1; + for (uint32_t i = 0; i < seats.size(); i++) { + if (seat == seats[i].seat) { + num = i; + break; + } + } + return num; +} + +void InputListenerManager::RegisterPointerListener(uint32_t caps, struct wl_seat *seat) +{ + struct wl_pointer *pointer = nullptr; + uint32_t num = FindSeatNum(seat); + pointer = seats[num].pointer; bool havePointerCapability = !!(caps & WL_SEAT_CAPABILITY_POINTER); if (havePointerCapability == true && pointer == nullptr) { static struct wl_pointer_listener listener = { @@ -474,10 +496,14 @@ void InputListenerManager::RegisterPointerListener(uint32_t caps) wl_pointer_destroy(pointer); pointer = nullptr; } + seats[num].pointer = pointer; } -void InputListenerManager::RegisterKeyboardListener(uint32_t caps) +void InputListenerManager::RegisterKeyboardListener(uint32_t caps, struct wl_seat *seat) { + struct wl_keyboard *keyboard = nullptr; + uint32_t num = FindSeatNum(seat); + keyboard = seats[num].keyboard; bool haveKeyboardCapability = !!(caps & WL_SEAT_CAPABILITY_KEYBOARD); if (haveKeyboardCapability == true && keyboard == nullptr) { static struct wl_keyboard_listener listener = { @@ -499,10 +525,14 @@ void InputListenerManager::RegisterKeyboardListener(uint32_t caps) wl_keyboard_destroy(keyboard); keyboard = nullptr; } + seats[num].keyboard = keyboard; } -void InputListenerManager::RegisterTouchListener(uint32_t caps) +void InputListenerManager::RegisterTouchListener(uint32_t caps, struct wl_seat *seat) { + struct wl_touch *touch = nullptr; + uint32_t num = FindSeatNum(seat); + touch = seats[num].touch; bool haveTouchCapability = !!(caps & WL_SEAT_CAPABILITY_TOUCH); if (haveTouchCapability == true && touch == nullptr) { static const struct wl_touch_listener listener = { @@ -525,5 +555,6 @@ void InputListenerManager::RegisterTouchListener(uint32_t caps) wl_touch_destroy(touch); touch = nullptr; } + seats[num].touch = touch; } } // namespace OHOS diff --git a/frameworks/wm/src/virtual_display_option.cpp b/frameworks/wm/src/virtual_display_option.cpp new file mode 100644 index 0000000000..1d31f0e1b5 --- /dev/null +++ b/frameworks/wm/src/virtual_display_option.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2021 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 "virtual_display_option_impl.h" + +namespace OHOS { +sptr VirtualDisplayOption::Get() +{ + return new VirtualDisplayOptionImpl; +} +} // namespace OHOS diff --git a/frameworks/wm/src/virtual_display_option_impl.cpp b/frameworks/wm/src/virtual_display_option_impl.cpp new file mode 100644 index 0000000000..f3905791e7 --- /dev/null +++ b/frameworks/wm/src/virtual_display_option_impl.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2021 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 "virtual_display_option_impl.h" + +#include "window_manager_hilog.h" + +namespace OHOS { +namespace { +constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "WMVirtualDisplayOptionImpl"}; +} + +WMError VirtualDisplayOptionImpl::SetX(int32_t x) +{ + this->x = x; + this->settingX = true; + return WM_OK; +} + +WMError VirtualDisplayOptionImpl::SetY(int32_t y) +{ + this->y = y; + this->settingY = true; + return WM_OK; +} + +WMError VirtualDisplayOptionImpl::SetWidth(uint32_t width) +{ + if (!(width > 0)) { + WMLOGFE("width is invalid, should > 0"); + return WM_ERROR_INVALID_PARAM; + } + + this->width = width; + this->settingWidth = true; + return WM_OK; +} + +WMError VirtualDisplayOptionImpl::SetHeight(uint32_t height) +{ + if (!(height > 0)) { + WMLOGFE("height is invalid, should > 0"); + return WM_ERROR_INVALID_PARAM; + } + + this->height = height; + this->settingHeight = true; + return WM_OK; +} + +int32_t VirtualDisplayOptionImpl::GetX() const +{ + return x; +} + +int32_t VirtualDisplayOptionImpl::GetY() const +{ + return y; +} + +uint32_t VirtualDisplayOptionImpl::GetWidth() const +{ + return width; +} + +uint32_t VirtualDisplayOptionImpl::GetHeight() const +{ + return height; +} + +bool VirtualDisplayOptionImpl::IsSettingX() const +{ + return settingX; +} + +bool VirtualDisplayOptionImpl::IsSettingY() const +{ + return settingY; +} + +bool VirtualDisplayOptionImpl::IsSettingWidth() const +{ + return settingWidth; +} + +bool VirtualDisplayOptionImpl::IsSettingHeight() const +{ + return settingHeight; +} +} // namespace OHOS diff --git a/frameworks/wm/src/window_impl.cpp b/frameworks/wm/src/window_impl.cpp index f14ec02ee5..ae013f5226 100644 --- a/frameworks/wm/src/window_impl.cpp +++ b/frameworks/wm/src/window_impl.cpp @@ -76,7 +76,8 @@ WMError WindowImpl::CreateRemoteWindow(sptr &wi, } auto windowManagerServer = SingletonContainer::Get(); - auto promise = windowManagerServer->CreateWindow(wi->wlSurface, 0, option->GetWindowType()); + auto promise = windowManagerServer->CreateWindow(wi->wlSurface, + option->GetDisplay(), option->GetWindowType()); if (promise == nullptr) { WMLOGFE("CreateWindow return nullptr promise"); return WM_ERROR_NEW; diff --git a/frameworks/wm/src/window_manager_impl.cpp b/frameworks/wm/src/window_manager_impl.cpp index d50d5913c2..0c04c2d0d5 100644 --- a/frameworks/wm/src/window_manager_impl.cpp +++ b/frameworks/wm/src/window_manager_impl.cpp @@ -192,6 +192,70 @@ sptr WindowManagerImpl::GetWindowByID(int32_t wid) return ret; } +WMError WindowManagerImpl::CreateVirtualDisplay(const sptr &option) +{ + if (wmservice == nullptr) { + return WM_ERROR_NOT_INIT; + } + + auto promise = wmservice->CreateVirtualDisplay(option->GetX(), option->GetY(), + option->GetWidth(), option->GetHeight()); + if (promise == nullptr) { + WMLOGFE("CreateVirtualDisplay return nullptr promise"); + return WM_ERROR_NEW; + } + + auto wret = promise->Await(); + if (wret != WM_OK) { + WMLOGFE("wms->CreateVirtualDisplay failed %{public}s", WMErrorStr(wret).c_str()); + return wret; + } + + return WM_OK; +} + +WMError WindowManagerImpl::DestroyVirtualDisplay(uint32_t did) +{ + if (wmservice == nullptr) { + return WM_ERROR_NOT_INIT; + } + + auto promise = wmservice->DestroyVirtualDisplay(did); + if (promise == nullptr) { + WMLOGFE("DestroyVirtualDisplay return nullptr promise"); + return WM_ERROR_NEW; + } + + auto wret = promise->Await(); + if (wret != WM_OK) { + WMLOGFE("wms->DestroyVirtualDisplay failed %{public}s", WMErrorStr(wret).c_str()); + return wret; + } + + return WM_OK; +} + +WMError WindowManagerImpl::SetDisplayMode(WMSDisplayMode mode) +{ + if (wmservice == nullptr) { + return WM_ERROR_NOT_INIT; + } + + auto promise = wmservice->SetDisplayMode(mode); + if (promise == nullptr) { + WMLOGFE("SetDisplayMode return nullptr promise"); + return WM_ERROR_NEW; + } + + auto wret = promise->Await(); + if (wret != WM_OK) { + WMLOGFE("wms->SetDisplayMode failed %{public}s", WMErrorStr(wret).c_str()); + return wret; + } + + return WM_OK; +} + WMError WindowManagerImpl::CreateWindow(sptr &window, const sptr &option) { if (option == nullptr) { diff --git a/frameworks/wm/src/wl_dma_buffer_factory.cpp b/frameworks/wm/src/wl_dma_buffer_factory.cpp index bb2515aa96..02e7d5dab1 100644 --- a/frameworks/wm/src/wl_dma_buffer_factory.cpp +++ b/frameworks/wm/src/wl_dma_buffer_factory.cpp @@ -134,7 +134,7 @@ bool PixelFormatToDrmFormat(int32_t pixelFormat, uint32_t &drmFormat) {PIXEL_FMT_RGBX_5551, DRM_FORMAT_RGBX5551}, {PIXEL_FMT_RGBA_5551, DRM_FORMAT_RGBA5551}, {PIXEL_FMT_RGBX_8888, DRM_FORMAT_RGBX8888}, - {PIXEL_FMT_RGBA_8888, DRM_FORMAT_ABGR8888}, + {PIXEL_FMT_RGBA_8888, DRM_FORMAT_RGBA8888}, {PIXEL_FMT_RGB_888, DRM_FORMAT_RGB888}, {PIXEL_FMT_BGR_565, DRM_FORMAT_BGR565}, {PIXEL_FMT_BGRX_4444, DRM_FORMAT_BGRX4444}, diff --git a/frameworks/wm/test/unittest/mock/mock_iwindow_manager_service.h b/frameworks/wm/test/unittest/mock/mock_iwindow_manager_service.h index f25c2e8c1f..71d06b7c75 100644 --- a/frameworks/wm/test/unittest/mock/mock_iwindow_manager_service.h +++ b/frameworks/wm/test/unittest/mock/mock_iwindow_manager_service.h @@ -47,6 +47,8 @@ public: MOCK_METHOD3(ScaleTo, sptr(int32_t wid, uint32_t width, uint32_t height)); MOCK_METHOD2(SetWindowType, sptr(int32_t wid, WindowType type)); MOCK_METHOD2(SetWindowMode, sptr(int32_t wid, WindowMode mode)); + MOCK_METHOD4(CreateVirtualDisplay, sptr(int32_t x, int32_t y, int32_t width, int32_t height)); + MOCK_METHOD1(DestroyVirtualDisplay, sptr(uint32_t did)); }; } // namespace OHOS diff --git a/frameworks/wmserver/BUILD.gn b/frameworks/wmserver/BUILD.gn index b0ff0b3fed..d05a998769 100644 --- a/frameworks/wmserver/BUILD.gn +++ b/frameworks/wmserver/BUILD.gn @@ -63,7 +63,6 @@ ohos_shared_library("wmserver") { "//drivers/peripheral/display/hal:hdi_display_device", "//foundation/multimodalinput/input/patch/diff_libinput_mmi:libinput-third-mmi", "//third_party/wayland_standard:wayland_core_protocol", - "//third_party/weston:drm-backend", "//third_party/weston:libexec_weston", "//utils/native/base:utils", ] diff --git a/frameworks/wmserver/protocol/wms.xml b/frameworks/wmserver/protocol/wms.xml index f8133f43e2..f8798ca8fc 100644 --- a/frameworks/wmserver/protocol/wms.xml +++ b/frameworks/wmserver/protocol/wms.xml @@ -44,6 +44,12 @@ + + + + + + @@ -51,6 +57,7 @@ + @@ -275,6 +282,22 @@ + + + + + + + + + + + + + + + + diff --git a/frameworks/wmserver/src/wmserver.c b/frameworks/wmserver/src/wmserver.c index 82d617e246..0adf2481b6 100644 --- a/frameworks/wmserver/src/wmserver.c +++ b/frameworks/wmserver/src/wmserver.c @@ -74,6 +74,7 @@ struct WindowSurface { int32_t height; int32_t lastSurfaceWidth; int32_t lastSurfaceHeight; + int32_t firstCommit; struct wl_list link; }; @@ -101,6 +102,11 @@ static struct WmsContext g_wmsCtx = {0}; static ScreenInfoChangeListener g_screenInfoChangeListener = NULL; static SeatInfoChangeListener g_seatInfoChangeListener = NULL; +static int32_t CreateScreen(struct WmsContext *pCtx, + struct weston_output *pOutput, + uint32_t screenType); +static void DestroyScreen(struct WmsScreen *pScreen); + static void SendGlobalWindowStatus(const struct WmsController *pController, uint32_t window_id, uint32_t status) { LOGD("start."); @@ -174,6 +180,12 @@ static inline int GetLayerId(uint32_t screenId, uint32_t type, uint32_t mode) return z + screenId * LAYER_ID_SCREEN_BASE; } +static inline int ChangeLayerId(uint32_t layerIdOld, uint32_t screenIdOld, uint32_t screenIdNew) +{ + uint32_t z = layerIdOld - screenIdOld * LAYER_ID_SCREEN_BASE; + return z + screenIdNew * LAYER_ID_SCREEN_BASE; +} + static void WindowSurfaceCommitted(struct weston_surface *surface, int32_t sx, int32_t sy); static struct WindowSurface *GetWindowSurface(const struct weston_surface *surface) @@ -218,15 +230,21 @@ static void SetSourceRectangle(const struct WindowSurface *windowSurface, (uint32_t)x, (uint32_t)y, (uint32_t)width, (uint32_t)height); } -static void SetDestinationRectangle(const struct WindowSurface *windowSurface, +static void SetDestinationRectangle(struct WindowSurface *windowSurface, int32_t x, int32_t y, int32_t width, int32_t height) { const struct ivi_layout_interface_for_wms *layoutInterface = windowSurface->controller->pWmsCtx->pLayoutInterface; struct ivi_layout_surface *layoutSurface = windowSurface->layoutSurface; const struct ivi_layout_surface_properties *prop = layoutInterface->get_properties_of_surface(layoutSurface); - layoutInterface->surface_set_transition(layoutSurface, - IVI_LAYOUT_TRANSITION_VIEW_DEFAULT, TIMER_INTERVAL_MS); // ms + if (windowSurface->firstCommit == 1) { + layoutInterface->surface_set_transition(layoutSurface, + IVI_LAYOUT_TRANSITION_VIEW_DEFAULT, TIMER_INTERVAL_MS); // ms + } else { + layoutInterface->surface_set_transition(layoutSurface, + IVI_LAYOUT_TRANSITION_NONE, TIMER_INTERVAL_MS); // ms + windowSurface->firstCommit = 1; + } if (width < 0) { width = prop->dest_width; @@ -364,7 +382,7 @@ static uint32_t GetWindowId(struct WmsController *pController) static struct ivi_layout_layer *GetLayer(struct weston_output *westonOutput, struct ivi_layout_interface_for_wms *pLayoutInterface, - uint32_t layerId) + uint32_t layerId, bool *isNewLayer) { LOGD("start."); struct ivi_layout_layer *layoutLayer = pLayoutInterface->get_layer_from_id(layerId); @@ -378,6 +396,8 @@ static struct ivi_layout_layer *GetLayer(struct weston_output *westonOutput, pLayoutInterface->screen_add_layer(westonOutput, layoutLayer); pLayoutInterface->layer_set_visibility(layoutLayer, true); + if (isNewLayer != NULL) + *isNewLayer = true; } LOGD("end."); @@ -410,18 +430,23 @@ static struct WmsScreen *GetScreen(const struct WindowSurface *windowSurface) static void CalcWindowInfo(struct WindowSurface *surface) { -#ifdef USE_DUMMY_SCREEN - int maxWidth = DUMMY_SCREEN_WIDTH; - int maxHeight = DUMMY_SCREEN_HEIGHT; -#else + struct WmsContext *ctx = surface->controller->pWmsCtx; struct WmsScreen *screen = GetScreen(surface); + int maxWidth = 0; + int maxHeight = 0; if (!screen) { LOGE("GetScreen error."); return; } - int maxWidth = screen->westonOutput->width; - int maxHeight = screen->westonOutput->height; -#endif /* USE_DUMMY_SCREEN */ + if (ctx->displayMode == WM_DISPLAY_MODE_EXPAND) { + wl_list_for_each(screen, &ctx->wlListScreen, wlListLink) { + maxWidth += screen->westonOutput->width; + } + maxHeight = ctx->pMainScreen->westonOutput->height; + } else { + maxWidth = screen->westonOutput->width; + maxHeight = screen->westonOutput->height; + } LayoutControllerInit(maxWidth, maxHeight); struct layout layout = {}; @@ -432,6 +457,78 @@ static void CalcWindowInfo(struct WindowSurface *surface) surface->height = layout.h; } +static bool AddSurface(struct WindowSurface *windowSurface, + uint32_t windowType, uint32_t windowMode) +{ + struct WmsContext *ctx = windowSurface->controller->pWmsCtx; + struct ivi_layout_interface_for_wms *layoutInterface = ctx->pLayoutInterface; + struct weston_output *mainWestonOutput = ctx->pMainScreen->westonOutput; + struct WmsScreen *screen = NULL; + int32_t x = mainWestonOutput->width; + + LOGD("start."); + + wl_list_for_each(screen, &ctx->wlListScreen, wlListLink) { + if (screen->screenId == windowSurface->screenId + || ctx->displayMode == WMS_DISPLAY_MODE_CLONE + || ctx->displayMode == WMS_DISPLAY_MODE_EXPAND) { + bool isNewLayer = false; + struct weston_output *westonOutput = screen->westonOutput; + uint32_t layerId = GetLayerId(screen->screenId, windowType, windowMode); + struct ivi_layout_layer *layoutLayer = GetLayer(screen->westonOutput, + layoutInterface, layerId, &isNewLayer); + if (!layoutLayer) { + LOGE("GetLayer failed."); + return false; + } + + if (screen->screenId != mainWestonOutput->id && isNewLayer) { + if (ctx->displayMode == WMS_DISPLAY_MODE_CLONE) { + layoutInterface->layer_set_source_rectangle(layoutLayer, 0, 0, + mainWestonOutput->width, mainWestonOutput->height); + } else if (ctx->displayMode == WMS_DISPLAY_MODE_EXPAND) { + layoutInterface->layer_set_source_rectangle(layoutLayer, x, 0, + westonOutput->width, mainWestonOutput->height); + x += westonOutput->width; + } + } + + layoutInterface->layer_add_surface(layoutLayer, windowSurface->layoutSurface); + } + } + layoutInterface->surface_set_visibility(windowSurface->layoutSurface, true); + + LOGD("end."); + return true; +} + +static bool RemoveSurface(struct WindowSurface *windowSurface) +{ + struct WmsContext *ctx = windowSurface->controller->pWmsCtx; + struct ivi_layout_interface_for_wms *layoutInterface = ctx->pLayoutInterface; + struct WmsScreen *screen = NULL; + + LOGD("start."); + + wl_list_for_each(screen, &ctx->wlListScreen, wlListLink) { + if (screen->screenId == windowSurface->screenId + || ctx->displayMode == WMS_DISPLAY_MODE_CLONE + || ctx->displayMode == WMS_DISPLAY_MODE_EXPAND) { + uint32_t layerId = GetLayerId(screen->screenId, windowSurface->type, windowSurface->mode); + struct ivi_layout_layer *layoutLayer = layoutInterface->get_layer_from_id(layerId); + if (!layoutLayer && screen->screenId == windowSurface->screenId) { + LOGE("get_layer_from_id failed. layerId=%{public}d", layerId); + continue; + } + + layoutInterface->layer_remove_surface(layoutLayer, windowSurface->layoutSurface); + } + } + + LOGD("end."); + return true; +} + static bool AddWindow(struct WindowSurface *windowSurface) { struct ivi_layout_layer *layoutLayer = NULL; @@ -440,20 +537,9 @@ static bool AddWindow(struct WindowSurface *windowSurface) LOGD("start."); - wl_list_for_each(screen, &ctx->wlListScreen, wlListLink) { - if (screen->screenId == windowSurface->screenId - || ctx->displayMode == WMS_DISPLAY_MODE_CLONE) { - uint32_t layerId = GetLayerId(screen->screenId, windowSurface->type, windowSurface->mode); - layoutLayer = GetLayer(screen->westonOutput, ctx->pLayoutInterface, layerId); - if (!layoutLayer) { - LOGE("GetLayer failed."); - return false; - } - ctx->pLayoutInterface->layer_add_surface(layoutLayer, - windowSurface->layoutSurface); - ctx->pLayoutInterface->surface_set_visibility( - windowSurface->layoutSurface, true); - } + if (!AddSurface(windowSurface, windowSurface->type, windowSurface->mode)) { + LOGE("AddSurface failed."); + return false; } // window position,size calc. @@ -557,6 +643,230 @@ static void ControllerCommitChanges(struct wl_client *client, LOGD("end."); } +static bool LayerCopySurfaces(struct WmsContext *ctx, struct ivi_layout_layer *layerFrom, + struct ivi_layout_layer *layerTo) +{ + LOGD("start."); + struct ivi_layout_surface **surfaces = NULL; + int32_t surfacesCount = 0; + uint32_t surfaceId = 0; + int32_t ret; + + ret = ctx->pLayoutInterface->get_surfaces_on_layer(layerFrom, &surfacesCount, &surfaces); + if (ret != IVI_SUCCEEDED) { + LOGE("ivi_layout_get_surfaces_on_layer failed."); + return false; + } + + for (int32_t surf_i = 0; surf_i < surfacesCount; surf_i++) { + ctx->pLayoutInterface->layer_add_surface(layerTo, surfaces[surf_i]); + } + + if (surfaces != NULL) { + free(surfaces); + } + + LOGD("end."); + return true; +} + +static bool ScreenCopyLayers(struct WmsContext *ctx, struct WmsScreen *screenFrom, + struct WmsScreen *screenTo) +{ + LOGD("start."); + struct ivi_layout_layer **layers = NULL; + int32_t layersCount = 0; + int32_t ret; + + ret = ctx->pLayoutInterface->get_layers_on_screen(screenFrom->westonOutput, &layersCount, &layers); + if (ret != IVI_SUCCEEDED) { + LOGE("ivi_layout_get_layers_on_screen failed."); + return false; + } + for (int32_t layer_i = 0; layer_i < layersCount; layer_i++) { + uint32_t layerIdOld = ctx->pLayoutInterface->get_id_of_layer(layers[layer_i]); + uint32_t layerIdNew = ChangeLayerId(layerIdOld, screenFrom->screenId, screenTo->screenId); + struct ivi_layout_layer *layerNew = GetLayer(screenTo->westonOutput, + ctx->pLayoutInterface, layerIdNew, NULL); + if (!layerNew) { + LOGE("GetLayer failed."); + free(layers); + return false; + } + + if (!LayerCopySurfaces(ctx, layers[layer_i], layerNew)) { + LOGE("LayerCopySurfaces failed."); + free(layers); + return false; + } + } + if (layers != NULL) { + free(layers); + } + + ctx->pLayoutInterface->commit_changes(); + LOGD("end."); + return true; +} + +static bool ScreenSetLayersSourceRect(struct WmsScreen *screen, + int32_t x, int32_t y, int32_t w, int32_t h) +{ + LOGD("start."); + struct WmsContext *ctx = screen->pWmsCtx; + struct ivi_layout_layer **layers = NULL; + int32_t layersCount = 0; + int32_t ret; + + ret = ctx->pLayoutInterface->get_layers_on_screen(screen->westonOutput, &layersCount, &layers); + if (ret != IVI_SUCCEEDED) { + LOGE("ivi_layout_get_layers_on_screen failed."); + return false; + } + for (int32_t layer_i = 0; layer_i < layersCount; layer_i++) { + ret = ctx->pLayoutInterface->layer_set_source_rectangle(layers[layer_i], x, y, w, h); + if (ret != IVI_SUCCEEDED) { + free(layers); + return false; + } + } + if (layers != NULL) { + free(layers); + } + + LOGD("end."); + return true; +} + +static bool ScreenClone(struct WmsScreen *screenFrom, struct WmsScreen *screenTo) +{ + LOGD("start."); + struct WmsContext *ctx = screenFrom->pWmsCtx; + bool ret; + + ret = ScreenCopyLayers(ctx, screenFrom, screenTo); + if (!ret) { + LOGE("ScreenCopyLayers failed."); + return ret; + } + + ret = ScreenSetLayersSourceRect(screenTo, 0, 0, + screenFrom->westonOutput->width, screenFrom->westonOutput->height); + if (!ret) { + LOGE("ScreenSetLayersSourceRect failed."); + return ret; + } + + LOGD("end."); + return true; +} + +static bool ScreenExpand(struct WmsScreen *screenMain, struct WmsScreen *screenExpand, + int32_t expandX, int32_t expandY) +{ + LOGD("start."); + struct WmsContext *ctx = screenMain->pWmsCtx; + bool ret; + + ret = ScreenCopyLayers(ctx, screenMain, screenExpand); + if (!ret) { + LOGE("ScreenCopyLayers failed."); + return ret; + } + + ret = ScreenSetLayersSourceRect(screenExpand, expandX, expandY, + screenExpand->westonOutput->width, screenMain->westonOutput->height); + if (!ret) { + LOGE("ScreenSetLayersSourceRect failed."); + return ret; + } + + LOGD("end."); + return true; +} + +static bool ScreenClear(struct WmsScreen *screen) +{ + LOGD("start."); + struct WmsContext *ctx = screen->pWmsCtx; + struct ivi_layout_layer **layers = NULL; + int32_t layersCount = 0; + int32_t ret; + + ret = ctx->pLayoutInterface->get_layers_on_screen(screen->westonOutput, &layersCount, &layers); + if (ret != IVI_SUCCEEDED) { + LOGE("ivi_layout_get_layers_on_screen failed."); + return false; + } + + for (int32_t layer_i = 0; layer_i < layersCount; layer_i++) { + struct ivi_layout_surface **surfaces = NULL; + int32_t surfacesCount = 0; + ret = ctx->pLayoutInterface->get_surfaces_on_layer(layers[layer_i], &surfacesCount, &surfaces); + if (ret != IVI_SUCCEEDED) { + LOGE("ivi_layout_get_surfaces_on_layer failed."); + return false; + } + for (int32_t surf_i = 0; surf_i < surfacesCount; surf_i++) { + ctx->pLayoutInterface->layer_remove_surface(layers[layer_i], surfaces[surf_i]); + } + if (surfaces != NULL) { + free(surfaces); + } + + ctx->pLayoutInterface->layer_set_source_rectangle(layers[layer_i], 0, 0, + screen->westonOutput->width, screen->westonOutput->height); + } + + if (layers != NULL) { + free(layers); + } + + LOGD("end."); + return true; +} + +static bool SetDisplayMode(struct WmsContext *ctx, uint32_t displayMode) +{ + struct WmsScreen *screen = NULL; + bool ret = true; + + ctx->pLayoutInterface->commit_changes(); + + if (ctx->displayMode != WMS_DISPLAY_MODE_SINGLE) { + wl_list_for_each(screen, &ctx->wlListScreen, wlListLink) { + if (screen->screenId == ctx->pMainScreen->screenId) { + continue; + } + ret = ScreenClear(screen); + LOGI("screen_clear, id: %{public}d, ret = %{public}d", screen->screenId, ret); + } + } + + int32_t x = ctx->pMainScreen->westonOutput->width; + if (displayMode == WMS_DISPLAY_MODE_CLONE + || displayMode == WMS_DISPLAY_MODE_EXPAND) { + wl_list_for_each(screen, &ctx->wlListScreen, wlListLink) { + if (screen->screenId == ctx->pMainScreen->screenId) { + continue; + } + if (displayMode == WMS_DISPLAY_MODE_CLONE) { + ret = ScreenClone(ctx->pMainScreen, screen); + LOGI("screen_clone from %{public}d to %{public}d, ret = %{public}d", + ctx->pMainScreen->screenId, screen->screenId, ret); + } else { + ret = ScreenExpand(ctx->pMainScreen, screen, x, 0); + x += screen->westonOutput->width; + LOGI("screen_expand from %{public}d to %{public}d, ret = %{public}d", + ctx->pMainScreen->screenId, screen->screenId, ret); + } + } + } + ctx->pLayoutInterface->commit_changes(); + + return ret; +} + static void ControllerSetDisplayMode(struct wl_client *client, struct wl_resource *resource, uint32_t displayMode) @@ -564,6 +874,7 @@ static void ControllerSetDisplayMode(struct wl_client *client, LOGD("start. displayMode %{public}d", displayMode); struct WmsController *controller = wl_resource_get_user_data(resource); struct WmsContext *ctx = controller->pWmsCtx; + bool ret = true; if (displayMode != WMS_DISPLAY_MODE_SINGLE && displayMode != WMS_DISPLAY_MODE_CLONE && @@ -577,23 +888,13 @@ static void ControllerSetDisplayMode(struct wl_client *client, if (ctx->displayMode == displayMode) { LOGE("current displayMode is the same."); - wms_send_reply_error(resource, WMS_ERROR_INVALID_PARAM); + wms_send_reply_error(resource, WMS_ERROR_OK); wl_client_flush(wl_resource_get_client(resource)); return; } - int32_t ret; - if (displayMode == WMS_DISPLAY_MODE_CLONE) { - ctx->pLayoutInterface->commit_changes(); - ret = ctx->pLayoutInterface->screen_clone(0, 1); - LOGE("screen_clone ret = %{public}d", ret); - } else { - ctx->pLayoutInterface->commit_changes(); - ret = ctx->pLayoutInterface->screen_clear(1); - LOGE("screen_clear ret = %{public}d", ret); - } - - if (ret == IVI_SUCCEEDED) { + ret = SetDisplayMode(ctx, displayMode); + if (ret == true) { ctx->displayMode = displayMode; wms_send_reply_error(resource, WMS_ERROR_OK); wl_client_flush(wl_resource_get_client(resource)); @@ -606,44 +907,78 @@ static void ControllerSetDisplayMode(struct wl_client *client, LOGD("end. displayMode %{public}d", ctx->displayMode); } -static void MoveWindowToLayerId(const struct WmsContext *wc, - const struct WindowSurface *ws, - struct wl_resource *wr, - uint32_t layerIdNew) +static void ControllerCreateVirtualDisplay(struct wl_client *pWlClient, + struct wl_resource *pWlResource, int32_t x, int32_t y, int32_t width, int32_t height) { - struct ivi_layout_layer *pLayoutLayerOld = NULL; - struct ivi_layout_layer *pLayoutLayerNew = NULL; - struct ivi_layout_interface_for_wms *pLayoutInterface = wc->pLayoutInterface; - struct WmsScreen *screen = NULL; + LOGD("start. CreateVirtualDisplay, x:%{public}d, y:%{public}d, " + "w:%{public}d, h:%{public}d", x, y, width, height); + struct WmsController *pWmsController = wl_resource_get_user_data(pWlResource); + struct WmsContext *pWmsCtx = pWmsController->pWmsCtx; + struct ivi_layout_interface_for_wms *pLayoutInterface = pWmsCtx->pLayoutInterface; + struct weston_output *pOutput = NULL; + struct WmsScreen *pScreen = NULL; - wl_list_for_each(screen, &wc->wlListScreen, wlListLink) { - if (screen->screenId == ws->screenId - || wc->displayMode == WMS_DISPLAY_MODE_CLONE) { - uint32_t layerIdOld = GetLayerId(screen->screenId, ws->type, ws->mode); - pLayoutLayerOld = pLayoutInterface->get_layer_from_id(layerIdOld); - if (!pLayoutLayerOld) { - if (screen->screenId == ws->screenId) { - LOGE("get_layer_from_id failed. layerId=%{public}d", layerIdOld); - wms_send_reply_error(wr, WMS_ERROR_INNER_ERROR); - wl_client_flush(wl_resource_get_client(wr)); - return; - } else { - continue; - } - } - - pLayoutLayerNew = GetLayer(screen->westonOutput, pLayoutInterface, layerIdNew); - if (!pLayoutLayerNew) { - LOGE("GetLayer failed."); - wms_send_reply_error(wr, WMS_ERROR_INNER_ERROR); - wl_client_flush(wl_resource_get_client(wr)); - return; - } - - pLayoutInterface->layer_remove_surface(pLayoutLayerOld, ws->layoutSurface); - pLayoutInterface->layer_add_surface(pLayoutLayerNew, ws->layoutSurface); + wl_list_for_each(pScreen, &pWmsCtx->wlListScreen, wlListLink) { + if (pScreen->screenType == WMS_SCREEN_TYPE_VIRTUAL) { + LOGE("virtual display already exists."); + wms_send_reply_error(pWlResource, WMS_ERROR_OK); + return; } } + pOutput = pLayoutInterface->create_virtual_screen(x, y, width, height); + if (pOutput == NULL) { + LOGE("layout create_virtual_screen failed."); + wms_send_reply_error(pWlResource, WMS_ERROR_NO_MEMORY); + return; + } + + if (CreateScreen(pWmsCtx, pOutput, WMS_SCREEN_TYPE_VIRTUAL) < 0) { + pLayoutInterface->destroy_virtual_screen(pOutput->id); + wms_send_reply_error(pWlResource, WMS_ERROR_NO_MEMORY); + return; + } + + wms_send_screen_status(pWlResource, pOutput->id, pOutput->name, WMS_SCREEN_STATUS_ADD, + pOutput->width, pOutput->height, WMS_SCREEN_TYPE_VIRTUAL); + wms_send_reply_error(pWlResource, WMS_ERROR_OK); + + wl_list_for_each(pWmsController, &pWmsCtx->wlListController, wlListLink) { + wms_send_screen_status(pWmsController->pWlResource, pOutput->id, pOutput->name, + WMS_SCREEN_STATUS_ADD, pOutput->width, pOutput->height, WMS_SCREEN_TYPE_VIRTUAL); + } + LOGD("end. CreateVirtualDisplay"); +} + +static void ControllerDestroyVirtualDisplay(struct wl_client *pWlClient, + struct wl_resource *pWlResource, + uint32_t screenID) +{ + LOGD("start. DestroyVirtualDisplay, screen id:%{public}d", screenID); + struct WmsController *pWmsController = wl_resource_get_user_data(pWlResource); + struct WmsContext *pWmsCtx = pWmsController->pWmsCtx; + struct ivi_layout_interface_for_wms *pLayoutInterface = pWmsCtx->pLayoutInterface; + struct WmsScreen *pScreen = NULL; + + pScreen = GetScreenFromId(pWmsCtx, screenID); + if (!pScreen || pScreen->screenType != WMS_SCREEN_TYPE_VIRTUAL) { + LOGE("screen is not found[%{public}d].", screenID); + wms_send_reply_error(pWlResource, WMS_ERROR_INVALID_PARAM); + return; + } + + pLayoutInterface->destroy_virtual_screen(screenID); + + DestroyScreen(pScreen); + + wms_send_screen_status(pWlResource, screenID, "", WMS_SCREEN_STATUS_REMOVE, + 0, 0, 0); + wms_send_reply_error(pWlResource, WMS_ERROR_OK); + + wl_list_for_each(pWmsController, &pWmsCtx->wlListController, wlListLink) { + wms_send_screen_status(pWmsController->pWlResource, screenID, "", + WMS_SCREEN_STATUS_REMOVE, 0, 0, 0); + } + LOGD("end. DestroyVirtualDisplay"); } static void SetWindowPosition(struct WindowSurface *ws, @@ -663,20 +998,18 @@ static void SetWindowSize(struct WindowSurface *ws, ws->height = height; } -static void SetWindowType(const struct WmsContext *wc, - const struct WindowSurface *ws, - struct wl_resource *wr, +static void SetWindowType(struct WindowSurface *ws, uint32_t windowType) { - MoveWindowToLayerId(wc, ws, wr, GetLayerId(ws->screenId, windowType, ws->mode)); + RemoveSurface(ws); + AddSurface(ws, windowType, ws->mode); } -static void SetWindowMode(const struct WmsContext *wc, - struct WindowSurface *ws, - struct wl_resource *wr, +static void SetWindowMode(struct WindowSurface *ws, uint32_t windowMode) { - MoveWindowToLayerId(wc, ws, wr, GetLayerId(ws->screenId, ws->type, windowMode)); + RemoveSurface(ws); + AddSurface(ws, ws->type, windowMode); } static void ControllerSetWindowType(struct wl_client *pWlClient, @@ -717,7 +1050,7 @@ static void ControllerSetWindowType(struct wl_client *pWlClient, return; } - SetWindowType(pWmsCtx, pWindowSurface, pWlResource, windowType); + SetWindowType(pWindowSurface, windowType); pWindowSurface->type = windowType; @@ -764,7 +1097,7 @@ static void ControllerSetWindowMode(struct wl_client *pWlClient, return; } - SetWindowMode(pWmsCtx, pWindowSurface, pWlResource, windowMode); + SetWindowMode(pWindowSurface, windowMode); pWindowSurface->mode = windowMode; wms_send_reply_error(pWlResource, WMS_ERROR_OK); wl_client_flush(wl_resource_get_client(pWlResource)); @@ -1346,7 +1679,7 @@ static void ControllerCreateWindow(struct wl_client *pWlClient, return; } - if (screenId > 0 && pWmsCtx->displayMode != WMS_DISPLAY_MODE_EXPAND) { + if (screenId > 0 && pWmsCtx->displayMode != WMS_DISPLAY_MODE_EXTEND) { LOGE("screenId %{public}d error.", screenId); wms_send_window_status(pWlResource, WMS_WINDOW_STATUS_FAILED, WINDOW_ID_INVALID, 0, 0, 0, 0); wl_client_flush(wl_resource_get_client(pWlResource)); @@ -1671,6 +2004,8 @@ static const struct wms_interface g_controllerImplementation = { ControllerCommitChanges, ControllerScreenshot, ControllerWindowshot, + ControllerCreateVirtualDisplay, + ControllerDestroyVirtualDisplay, }; static void UnbindWmsController(struct wl_resource *pResource) @@ -1730,24 +2065,14 @@ static void BindWmsController(struct wl_client *pClient, wl_list_init(&pController->stListener.frameListener.link); wl_list_init(&pController->stListener.outputDestroyed.link); + struct WmsScreen *pScreen = NULL; struct weston_output *pOutput = NULL; - wl_list_for_each(pOutput, &pCtx->pCompositor->output_list, link) { + wl_list_for_each(pScreen, &pCtx->wlListScreen, wlListLink) { + pOutput = pScreen->westonOutput; wms_send_screen_status(pController->pWlResource, pOutput->id, pOutput->name, WMS_SCREEN_STATUS_ADD, -#ifdef USE_DUMMY_SCREEN - DUMMY_SCREEN_WIDTH, DUMMY_SCREEN_HEIGHT); -#else - pOutput->width, pOutput->height); -#endif /* USE_DUMMY_SCREEN */ - wl_client_flush(wl_resource_get_client(pController->pWlResource)); + pOutput->width, pOutput->height, pScreen->screenType); } -#ifdef USE_DUMMY_SCREEN - pOutput = pCtx->pLayoutInterface->get_dummy_output(); - wms_send_screen_status(pController->pWlResource, pOutput->id, pOutput->name, WMS_SCREEN_STATUS_ADD, - pOutput->width, pOutput->height); - wl_client_flush(wl_resource_get_client(pController->pWlResource)); -#endif /* USE_DUMMY_SCREEN */ - uint32_t flag = GetDisplayModeFlag(pController->pWmsCtx); wms_send_display_mode(pController->pWlResource, flag); wl_client_flush(wl_resource_get_client(pController->pWlResource)); @@ -1822,7 +2147,8 @@ static void WmsControllerDestroy(struct wl_listener *listener, void *data) } static int32_t CreateScreen(struct WmsContext *pCtx, - struct weston_output *pOutput) + struct weston_output *pOutput, + uint32_t screenType) { struct WmsScreen *pScreen = NULL; @@ -1834,8 +2160,13 @@ static int32_t CreateScreen(struct WmsContext *pCtx, pScreen->pWmsCtx = pCtx; pScreen->westonOutput = pOutput; pScreen->screenId = pOutput->id; + pScreen->screenType = screenType; - wl_list_insert(&pCtx->wlListScreen, &pScreen->wlListLink); + if (pScreen->screenId == 0) { + pCtx->pMainScreen = pScreen; + } + + wl_list_insert(pCtx->wlListScreen.prev, &pScreen->wlListLink); return 0; } @@ -1868,10 +2199,12 @@ static void OutputCreatedEvent(struct wl_listener *listener, void *data) struct WmsContext *ctx = wl_container_of(listener, ctx, wlListenerOutputCreated); struct weston_output *createdOutput = (struct weston_output*)data; - CreateScreen(ctx, createdOutput); + CreateScreen(ctx, createdOutput, WMS_SCREEN_TYPE_PHYSICAL); DisplayModeUpdate(ctx); + SetDisplayMode(ctx, ctx->displayMode); + ScreenInfoChangerNotify(); LOGD("end."); @@ -1953,11 +2286,9 @@ static int WmsContextInit(struct WmsContext *ctx, struct weston_compositor *comp } ctx->wlListenerDestroy.notify = WmsControllerDestroy; -#ifdef USE_DUMMY_SCREEN - ctx->displayMode = WMS_DISPLAY_MODE_CLONE; -#else - ctx->displayMode = WMS_DISPLAY_MODE_SINGLE; -#endif + + ctx->displayMode = WMS_DISPLAY_MODE_EXTEND; + wl_signal_add(&compositor->destroy_signal, &ctx->wlListenerDestroy); LayoutControllerInit(0, 0); @@ -1977,22 +2308,13 @@ WL_EXPORT int wet_module_init(struct weston_compositor *compositor, } wl_list_for_each(output, &compositor->output_list, link) { - if (CreateScreen(ctx, output) < 0) { + if (CreateScreen(ctx, output, WMS_SCREEN_TYPE_PHYSICAL) < 0) { WmsScreenDestroy(ctx); free(ctx); return -1; } } -#ifdef USE_DUMMY_SCREEN - output = ctx->pLayoutInterface->get_dummy_output(); - if (CreateScreen(ctx, output) < 0) { - WmsScreenDestroy(ctx); - free(ctx); - return -1; - } -#endif /* USE_DUMMY_SCREEN */ - ScreenInfoInit(compositor); LOGD("end."); diff --git a/frameworks/wmserver/src/wmserver.h b/frameworks/wmserver/src/wmserver.h index ac6a672b5a..ce14940daf 100644 --- a/frameworks/wmserver/src/wmserver.h +++ b/frameworks/wmserver/src/wmserver.h @@ -44,6 +44,7 @@ struct WmsContext { struct wl_listener wlListenerOutputDestroyed; struct wl_listener wlListenerSeatCreated; uint32_t displayMode; + struct WmsScreen *pMainScreen; #ifdef USE_IVI_INPUT_FOCUS const struct ivi_input_interface_for_wms *pInputInterface; #endif @@ -63,6 +64,7 @@ struct WmsScreen { struct wl_list wlListLink; struct WmsContext *pWmsCtx; uint32_t screenId; + uint32_t screenType; struct weston_output *westonOutput; }; diff --git a/frameworks/wmservice/include/window_manager_service_proxy.h b/frameworks/wmservice/include/window_manager_service_proxy.h index 2033c49710..9c855b9973 100644 --- a/frameworks/wmservice/include/window_manager_service_proxy.h +++ b/frameworks/wmservice/include/window_manager_service_proxy.h @@ -57,9 +57,11 @@ public: virtual sptr ScaleTo(int32_t wid, uint32_t width, uint32_t height) override; virtual sptr SetWindowType(int32_t wid, WindowType type) override; virtual sptr SetWindowMode(int32_t wid, WindowMode mode) override; + virtual sptr CreateVirtualDisplay(int32_t x, int32_t y, int32_t width, int32_t height) override; + virtual sptr DestroyVirtualDisplay(uint32_t did) override; static void OnReply(wms_error); - static void OnDisplayChange(uint32_t, const char *, wms_screen_status, int32_t, int32_t); + static void OnDisplayChange(uint32_t, const char *, wms_screen_status, int32_t, int32_t, wms_screen_type type); static void OnDisplayPower(uint32_t, int32_t); static void OnDisplayBacklight(uint32_t, uint32_t); static void OnDisplayModeChange(uint32_t); diff --git a/frameworks/wmservice/src/window_manager_service_client_impl.cpp b/frameworks/wmservice/src/window_manager_service_client_impl.cpp index f58cdf4594..10936a1894 100644 --- a/frameworks/wmservice/src/window_manager_service_client_impl.cpp +++ b/frameworks/wmservice/src/window_manager_service_client_impl.cpp @@ -48,9 +48,10 @@ void OnReply(void *, struct wms *, uint32_t a) } void OnDisplayChange(void *, struct wms *, - uint32_t a, const char *b, uint32_t c, int32_t d, int32_t e) + uint32_t a, const char *b, uint32_t c, int32_t d, int32_t e, uint32_t f) { - WindowManagerServiceProxy::OnDisplayChange(a, b, static_cast(c), d, e); + WindowManagerServiceProxy::OnDisplayChange(a, b, static_cast(c), d, e, + static_cast(f)); } void OnDisplayPower(void *, struct wms *, uint32_t a, int32_t b) diff --git a/frameworks/wmservice/src/window_manager_service_proxy.cpp b/frameworks/wmservice/src/window_manager_service_proxy.cpp index 0c269aa162..d73a8f5cc4 100644 --- a/frameworks/wmservice/src/window_manager_service_proxy.cpp +++ b/frameworks/wmservice/src/window_manager_service_proxy.cpp @@ -66,7 +66,7 @@ void WindowManagerServiceProxy::OnReply(wms_error error) } void WindowManagerServiceProxy::OnDisplayChange(uint32_t did, - const char *name, wms_screen_status state, int32_t width, int32_t height) + const char *name, wms_screen_status state, int32_t width, int32_t height, wms_screen_type type) { WMLOGFI("state: %{public}d, did: %{public}d, %{public}s(%{public}dx%{public}d)", state, did, name, width, height); @@ -84,6 +84,7 @@ void WindowManagerServiceProxy::OnDisplayChange(uint32_t did, .phyWidth = width, .phyHeight = height, .vsync = tmpVsyncFreq, + .type = static_cast(type), }; displays.push_back(info); } @@ -475,4 +476,27 @@ sptr WindowManagerServiceProxy::SetWindowMode(int32_t wid, Windo wl_display_flush(display); return ret; } + +sptr WindowManagerServiceProxy::CreateVirtualDisplay( + int32_t x, int32_t y, int32_t width, int32_t height) +{ + sptr ret = new PromiseWMError(); + std::lock_guard lock(promiseQueueMutex); + promiseQueue.push(ret); + wms_create_virtual_display(wms, x, y, width, height); + wms_commit_changes(wms); + wl_display_flush(display); + return ret; +} + +sptr WindowManagerServiceProxy::DestroyVirtualDisplay(uint32_t did) +{ + sptr ret = new PromiseWMError(); + std::lock_guard lock(promiseQueueMutex); + promiseQueue.push(ret); + wms_destroy_virtual_display(wms, did); + wms_commit_changes(wms); + wl_display_flush(display); + return ret; +} } // namespace OHOS diff --git a/frameworks/wmtest/BUILD.gn b/frameworks/wmtest/BUILD.gn index de7f93f099..2dedd7984f 100644 --- a/frameworks/wmtest/BUILD.gn +++ b/frameworks/wmtest/BUILD.gn @@ -33,10 +33,15 @@ ohos_executable("wmtest") { sources = [ "frameworks/inative_test.cpp", "frameworks/main.cpp", + "frameworks/main_option.cpp", "frameworks/native_test_class.cpp", "frameworks/util.cpp", + ] + + sources += [ "test/crash_native_test_1.cpp", "test/crash_native_test_2.cpp", + "test/dumper_test_1.cpp", "test/other_native_test_1.cpp", "test/pref_native_test_1.cpp", "test/vsync_native_test_1.cpp", @@ -58,6 +63,9 @@ ohos_executable("wmtest") { "test/wmclient_native_test_29.cpp", "test/wmclient_native_test_30.cpp", "test/wmclient_native_test_32.cpp", + "test/wmclient_native_test_33.cpp", + "test/wmclient_native_test_34.cpp", + "test/wmclient_native_test_35.cpp", "test/wmclient_native_test_4.cpp", "test/wmclient_native_test_5.cpp", "test/wmclient_native_test_6.cpp", @@ -80,9 +88,11 @@ ohos_executable("wmtest") { deps = [ "//foundation/communication/ipc/interfaces/innerkits/ipc_core:ipc_core", "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/graphic/standard:libgraphic_dumper_client", "//foundation/graphic/standard:libvsync_client", "//foundation/graphic/standard:libwmclient", "//foundation/graphic/standard:libwmservice", + "//foundation/graphic/standard/utils:option_parser", "//foundation/multimodalinput/input/frameworks/proxy:libmmi-client", "//third_party/zlib:libz", ] diff --git a/frameworks/wmtest/frameworks/main.cpp b/frameworks/wmtest/frameworks/main.cpp index c0ab1856a8..29c6834514 100644 --- a/frameworks/wmtest/frameworks/main.cpp +++ b/frameworks/wmtest/frameworks/main.cpp @@ -24,13 +24,16 @@ #include #include "inative_test.h" +#include "main_option.h" +#include "native_test_class.h" using namespace OHOS; namespace { void Usage(const char *argv0) { - printf("Usage: %s type id\n", argv0); + std::cerr << "Usage: " << argv0 << " [option] type id" << std::endl; + std::cerr << "-d, --display[=0] Created Window's Display ID" << std::endl; auto visitFunc = [](const INativeTest *test) { std::stringstream ss; ss << test->GetDomain() << ", id="; @@ -48,37 +51,34 @@ void Usage(const char *argv0) int32_t main(int32_t argc, const char **argv) { - constexpr int32_t argNumber = 2; - if (argc <= argNumber) { - Usage(argv[0]); - return 0; - } - - int32_t testcase = -1; - constexpr int32_t domainIndex = 1; - constexpr int32_t idIndex = 2; - std::stringstream ss(argv[idIndex]); - ss >> testcase; - if (!ss || testcase == -1) { + // parse option + MainOption option; + if (option.Parse(argc, argv)) { + std::cerr << option.GetErrorString() << std::endl; Usage(argv[0]); return 1; } + // find test INativeTest *found = nullptr; - auto visitFunc = [argv, testcase, &found](INativeTest *test) { - if (test->GetDomain() == argv[domainIndex] && test->GetID() == testcase) { + auto visitFunc = [&option, &found](INativeTest *test) { + if (test->GetDomain() == option.domain && test->GetID() == option.testcase) { found = test; } }; INativeTest::VisitTests(visitFunc); if (found == nullptr) { - printf("not found test %d\n", testcase); + printf("not found test %d\n", option.testcase); return 1; } + // default value assign + NativeTestFactory::defaultDisplayID = option.displayID; + + // run test auto runner = AppExecFwk::EventRunner::Create(false); auto handler = std::make_shared(runner); - handler->PostTask(std::bind(&INativeTest::Run, found, argc - argNumber, argv + argNumber)); + handler->PostTask(std::bind(&INativeTest::Run, found, option.GetSkippedArgc(), option.GetSkippedArgv())); if (found->GetLastTime() != INativeTest::LAST_TIME_FOREVER) { handler->PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner), found->GetLastTime()); } diff --git a/frameworks/wmtest/frameworks/main_option.cpp b/frameworks/wmtest/frameworks/main_option.cpp new file mode 100644 index 0000000000..ab9e953612 --- /dev/null +++ b/frameworks/wmtest/frameworks/main_option.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021 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 "main_option.h" + +MainOption::MainOption() +{ + AddArguments(domain); + AddArguments(testcase); + AddOption("d", "display", displayID); +} + +int32_t MainOption::Parse(int32_t argc, const char **argv) +{ + // ignore wmtest(argv0) + return OptionParser::Parse(argc - 1, argv + 1); +} diff --git a/frameworks/wmtest/frameworks/main_option.h b/frameworks/wmtest/frameworks/main_option.h new file mode 100644 index 0000000000..efab5a273a --- /dev/null +++ b/frameworks/wmtest/frameworks/main_option.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_WMTEST_FRAMEWORKS_MAIN_OPTION_H +#define FRAMEWORKS_WMTEST_FRAMEWORKS_MAIN_OPTION_H + +#include + +class MainOption : public OptionParser { +public: + MainOption(); + int32_t Parse(int32_t argc, const char **argv); + + // attr + std::string domain = ""; + int32_t testcase = -1; + int32_t displayID = 0; +}; + +#endif // FRAMEWORKS_WMTEST_FRAMEWORKS_MAIN_OPTION_H diff --git a/frameworks/wmtest/frameworks/native_test_class.cpp b/frameworks/wmtest/frameworks/native_test_class.cpp index 7f54a1350f..86bcacd9ce 100644 --- a/frameworks/wmtest/frameworks/native_test_class.cpp +++ b/frameworks/wmtest/frameworks/native_test_class.cpp @@ -33,7 +33,9 @@ #define NUMBER_VERTICES 4 namespace OHOS { -sptr NativeTestFactory::CreateWindow(WindowType type, sptr csurface) +sptr NativeTestFactory::CreateWindow(WindowType type, + sptr csurface, + std::optional did) { auto wm = WindowManager::GetInstance(); if (wm == nullptr) { @@ -48,6 +50,7 @@ sptr NativeTestFactory::CreateWindow(WindowType type, sptr csur sptr window; option->SetWindowType(type); option->SetConsumerSurface(csurface); + option->SetDisplay(did.value_or(defaultDisplayID)); wm->CreateWindow(window, option); if (window == nullptr) { printf("NativeTestFactory::CreateWindow return nullptr\n"); diff --git a/frameworks/wmtest/frameworks/native_test_class.h b/frameworks/wmtest/frameworks/native_test_class.h index 06794fc6ca..ab8609df6f 100644 --- a/frameworks/wmtest/frameworks/native_test_class.h +++ b/frameworks/wmtest/frameworks/native_test_class.h @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -40,7 +41,10 @@ typedef struct { class NativeTestFactory { public: - static sptr CreateWindow(WindowType, sptr csurface = nullptr); + static sptr CreateWindow(WindowType type, + sptr csurface = nullptr, + std::optional did = std::nullopt); + static inline int32_t defaultDisplayID = 0; }; using DrawFunc = std::function; diff --git a/frameworks/wmtest/test/dumper_test_1.cpp b/frameworks/wmtest/test/dumper_test_1.cpp new file mode 100644 index 0000000000..2fde7ea9bd --- /dev/null +++ b/frameworks/wmtest/test/dumper_test_1.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2021 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 "other_native_test_1.h" + +#include +#include +#include + +#include +#include + +#include "inative_test.h" +#include "native_test_class.h" +#include "util.h" + +using namespace OHOS; + +namespace { +class DumperTest1 : public INativeTest { +public: + std::string GetDescription() const override + { + constexpr const char *desc = "dumper native test"; + return desc; + } + + std::string GetDomain() const override + { + constexpr const char *domain = "!dumper"; + return domain; + } + + int32_t GetID() const override + { + constexpr int32_t id = 1; + return id; + } + + uint32_t GetLastTime() const override + { + constexpr uint32_t lastTime = LAST_TIME_FOREVER; + return lastTime; + } + + static void Handler(int32_t signal) + { + int32_t signals[] = {SIGINT, SIGKILL, SIGTERM, SIGTSTP, SIGQUIT, SIGHUP}; + for (uint32_t i = 0; i < sizeof(signals) / sizeof(*signals); i++) { + if (signals[i] == signal) { + ExitTest(); + break; + } + } + } + + void Run(int32_t argc, const char **argv) override + { + handler = AppExecFwk::EventHandler::Current(); + printf("graphic dumper test start!\n"); + std::signal(SIGINT, Handler); + std::signal(SIGKILL, Handler); + std::signal(SIGTERM, Handler); + std::signal(SIGTSTP, Handler); + std::signal(SIGQUIT, Handler); + std::signal(SIGHUP, Handler); + + OptionParser parser; + parser.AddArguments(tagInfo); + parser.Parse(argc, argv); + + dumper = GraphicDumperHelper::GetInstance(); + configListener = dumper->AddConfigChangeListener(tagInfo + ".info", + std::bind(&DumperTest1::OnConfigChange, this, std::placeholders::_1, std::placeholders::_2)); + dumpListener = dumper->AddDumpListener(tagInfo + ".info", std::bind(&DumperTest1::OnDump, this)); + + AfterRun(); + } + + void AfterRun() + { + auto str = "ABCEDFGHIG0123456789ABCEDFGHIG0123456789ABCEDFGHIG0123456789"; + int32_t ret = dumper->SendInfo("log." + tagInfo, "[%d]%s just for test log %d!!!\n", getpid(), str, count++); + if (ret != 0) { + printf("graphic dumper service died!\n"); + ExitDump(); + return; + } + + ret = dumper->SendInfo("log." + tagInfo + ".1", "[%d]%s\njust for test2 log %d!!!\n", getpid(), str, count++); + if (ret != 0) { + printf("graphic dumper service died!\n"); + ExitDump(); + } + + constexpr int32_t delayTime = 10; + PostTask(std::bind(&DumperTest1::AfterRun, this), delayTime); + } + + void ExitDump() + { + if (configListener != 0) { + dumper->RemoveConfigChangeListener(configListener); + } + if (dumpListener != 0) { + dumper->RemoveDumpListener(dumpListener); + } + ExitTest(); + } + + void OnConfigChange(const std::string &key, const std::string &val) + { + auto func = [this]() { + auto str = "********** !!! just for test send info !!! **********\n"; + int32_t ret = dumper->SendInfo(tagInfo, str); + printf("graphic dumper ret = %d\n", ret); + if (ret != 0) { + printf("graphic dumper service died!\n"); + handler->PostTask(std::bind(&DumperTest1::ExitDump, this)); + } + }; + + printf("%s -> %s\n", key.c_str(), val.c_str()); + if (key.find("info") != std::string::npos && val.compare("true") == 0) { + handler->PostTask(func); + } + } + + void OnDump() + { + printf("OnDump\n"); + dumper->SendInfo(tagInfo, "pid[%d] send dump info \n", getpid()); + } + +private: + static inline std::shared_ptr handler = nullptr; + std::string tagInfo = "A.B.info"; + sptr dumper = nullptr; + int32_t configListener = 0; + int32_t dumpListener = 0; + int32_t count = 0; +} g_autoload; +} // namespace diff --git a/frameworks/wmtest/test/dumper_test_1.h b/frameworks/wmtest/test/dumper_test_1.h new file mode 100644 index 0000000000..344bd06adf --- /dev/null +++ b/frameworks/wmtest/test/dumper_test_1.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_WMTEST_TEST_DUMPER_TEST_1 +#define FRAMEWORKS_WMTEST_TEST_DUMPER_TEST_1 + +#endif // FRAMEWORKS_WMTEST_TEST_DUMPER_TEST_1 diff --git a/frameworks/wmtest/test/pref_native_test_1.cpp b/frameworks/wmtest/test/pref_native_test_1.cpp index 9b73e5e8da..dac6372e68 100644 --- a/frameworks/wmtest/test/pref_native_test_1.cpp +++ b/frameworks/wmtest/test/pref_native_test_1.cpp @@ -17,8 +17,9 @@ #include #include -#include +#include +#include #include #include "inative_test.h" @@ -56,16 +57,11 @@ public: void Run(int32_t argc, const char **argv) override { - if (argc <= 1) { - printf("need a compress size\n"); - ExitTest(); - return; - } - - uint32_t size = -1; - int ret = sscanf_s(argv[1], "%u", &size); - if (ret == 0) { - printf("%s parse argv[2] failed\n", __func__); + OptionParser parser; + int32_t size = -1; + parser.AddArguments(size); + if (parser.Parse(argc, argv)) { + std::cerr << parser.GetErrorString() << std::endl; ExitTest(); return; } diff --git a/frameworks/wmtest/test/wmclient_native_test_2.cpp b/frameworks/wmtest/test/wmclient_native_test_2.cpp index 3c61b4c739..a88262a1f2 100644 --- a/frameworks/wmtest/test/wmclient_native_test_2.cpp +++ b/frameworks/wmtest/test/wmclient_native_test_2.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include "inative_test.h" @@ -76,15 +77,8 @@ public: } } - bool CheckArguments(const char *argv1, int &typeId) + bool CheckArguments(int32_t typeId) { - std::stringstream ss(argv1); - ss >> typeId; - if (!ss.eof() || !ss) { - printf("input error\n"); - return false; - } - if (typeId < 0 || typeId > WINDOW_TYPE_MAX) { printf ("input id is %d, not with rules!!!\n", typeId); return false; @@ -95,8 +89,17 @@ public: void Run(int32_t argc, const char **argv) override { - int type = -1; - if (argc == 1 || (!CheckArguments(argv[1], type))) { + OptionParser parser; + int32_t type = -1; + parser.AddArguments(type); + if (parser.Parse(argc, argv)) { + std::cerr << parser.GetErrorString() << std::endl; + Usage(); + ExitTest(); + return; + } + + if (!CheckArguments(type)) { Usage(); ExitTest(); return; @@ -112,13 +115,14 @@ public: window = NativeTestFactory::CreateWindow(static_cast(type)); if (window == nullptr) { printf("NativeTestFactory::CreateWindow return nullptr\n"); + ExitTest(); return; } window->SwitchTop(); auto surface = window->GetSurface(); windowSync = NativeTestSync::CreateSync(NativeTestDraw::FlushDraw, surface); - } + } private: sptr window = nullptr; diff --git a/frameworks/wmtest/test/wmclient_native_test_33.cpp b/frameworks/wmtest/test/wmclient_native_test_33.cpp new file mode 100644 index 0000000000..38ba7dbb8a --- /dev/null +++ b/frameworks/wmtest/test/wmclient_native_test_33.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2021 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 "wmclient_native_test_33.h" + +#include +#include + +#include +#include + +#include "inative_test.h" +#include "native_test_class.h" +#include "util.h" + +using namespace OHOS; + +namespace { +constexpr int32_t VIRTUAL_DISPLAY_X = 100; +constexpr int32_t VIRTUAL_DISPLAY_Y = 10; +constexpr int32_t VIRTUAL_DISPLAY_W = 500; +constexpr int32_t VIRTUAL_DISPLAY_H = 500; + +class WMClientNativeTest33 : public INativeTest { +public: + std::string GetDescription() const override + { + constexpr const char *desc = "virtual display create"; + return desc; + } + + std::string GetDomain() const override + { + constexpr const char *domain = "wmclient"; + return domain; + } + + int32_t GetID() const override + { + constexpr int32_t id = 33; + return id; + } + + uint32_t GetLastTime() const override + { + constexpr uint32_t lastTime = 5000; + return lastTime; + } + + void Run(int32_t argc, const char **argv) override + { + auto wm = WindowManager::GetInstance(); + if (wm == nullptr) { + printf("WindowManager::GetInstance failed.\n"); + return; + } + + auto wmRet = wm->Init(); + if (wmRet) { + printf("init failed with %s\n", WMErrorStr(wmRet).c_str()); + ExitTest(); + return; + } + + wm->GetDisplays(displays); + for (display = displays.begin(); display != displays.end(); display++) { + if (display->type == DISPLAY_TYPE_VIRTUAL) + break; + } + + if (display != displays.end()) { + printf("virtual display already extsis.\n"); + } else { + auto virtualDisplayOption = VirtualDisplayOption::Get(); + if (virtualDisplayOption == nullptr) { + printf("VirtualDisplayOption::Get failed.\n"); + return; + } + virtualDisplayOption->SetX(VIRTUAL_DISPLAY_X); + virtualDisplayOption->SetY(VIRTUAL_DISPLAY_Y); + virtualDisplayOption->SetWidth(VIRTUAL_DISPLAY_W); + virtualDisplayOption->SetHeight(VIRTUAL_DISPLAY_H); + + auto ret = wm->CreateVirtualDisplay(virtualDisplayOption); + if (ret != WM_OK) { + printf("create virtual display failed.\n"); + return; + } + printf("create virtual display succeed.\n"); + } + + wm->GetDisplays(displays); + for (display = displays.begin(); display != displays.end(); display++) { + if (display->type == DISPLAY_TYPE_VIRTUAL) + break; + } + + window = NativeTestFactory::CreateWindow(WINDOW_TYPE_NORMAL, nullptr, display->id); + if (window == nullptr) { + printf("NativeTestFactory::CreateWindow return nullptr\n"); + return; + } + + window->SwitchTop(); + auto surface = window->GetSurface(); + windowSync = NativeTestSync::CreateSync(NativeTestDraw::FlushDraw, surface); + } + +private: + std::vector displays; + std::vector::iterator display; + sptr window = nullptr; + sptr windowSync = nullptr; +} g_autoload; +} diff --git a/frameworks/wmtest/test/wmclient_native_test_33.h b/frameworks/wmtest/test/wmclient_native_test_33.h new file mode 100644 index 0000000000..9577d88dc0 --- /dev/null +++ b/frameworks/wmtest/test/wmclient_native_test_33.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_WMTEST_TEST_WMCLIENT_WMCLIENT_NATIVE_TEST_33_H +#define FRAMEWORKS_WMTEST_TEST_WMCLIENT_WMCLIENT_NATIVE_TEST_33_H + +#endif // FRAMEWORKS_WMTEST_TEST_WMCLIENT_WMCLIENT_NATIVE_TEST_33_H diff --git a/frameworks/wmtest/test/wmclient_native_test_34.cpp b/frameworks/wmtest/test/wmclient_native_test_34.cpp new file mode 100644 index 0000000000..ee497ab022 --- /dev/null +++ b/frameworks/wmtest/test/wmclient_native_test_34.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2021 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 "wmclient_native_test_34.h" + +#include +#include + +#include +#include + +#include "inative_test.h" +#include "native_test_class.h" +#include "util.h" + +using namespace OHOS; + +namespace { +class WMClientNativeTest34 : public INativeTest { +public: + std::string GetDescription() const override + { + constexpr const char *desc = "virtual display destory"; + return desc; + } + + std::string GetDomain() const override + { + constexpr const char *domain = "wmclient"; + return domain; + } + + int32_t GetID() const override + { + constexpr int32_t id = 34; + return id; + } + + uint32_t GetLastTime() const override + { + constexpr uint32_t lastTime = 1000; + return lastTime; + } + + void Run(int32_t argc, const char **argv) override + { + auto wm = WindowManager::GetInstance(); + if (wm == nullptr) { + printf("WindowManager::GetInstance failed.\n"); + return; + } + + auto wmRet = wm->Init(); + if (wmRet) { + printf("init failed with %s\n", WMErrorStr(wmRet).c_str()); + ExitTest(); + return; + } + + wm->GetDisplays(displays); + for (display = displays.begin(); display != displays.end(); display++) { + if (display->type == DISPLAY_TYPE_VIRTUAL) + break; + } + + if (display == displays.end()) { + printf("virtual display non-existent.\n"); + } else { + auto ret = wm->DestroyVirtualDisplay(display->id); + if (ret != WM_OK) { + printf("destroy virtual display failed.\n"); + return; + } + printf("virtual display destroy succeed.\n"); + } + } + +private: + std::vector displays; + std::vector::iterator display; + sptr window; + sptr windowSync; +} g_autoload; +} diff --git a/frameworks/wmtest/test/wmclient_native_test_34.h b/frameworks/wmtest/test/wmclient_native_test_34.h new file mode 100644 index 0000000000..0082399ad3 --- /dev/null +++ b/frameworks/wmtest/test/wmclient_native_test_34.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_WMTEST_TEST_WMCLIENT_WMCLIENT_NATIVE_TEST_34_H +#define FRAMEWORKS_WMTEST_TEST_WMCLIENT_WMCLIENT_NATIVE_TEST_34_H + +#endif // FRAMEWORKS_WMTEST_TEST_WMCLIENT_WMCLIENT_NATIVE_TEST_34_H diff --git a/frameworks/wmtest/test/wmclient_native_test_35.cpp b/frameworks/wmtest/test/wmclient_native_test_35.cpp new file mode 100644 index 0000000000..ab0e29dcca --- /dev/null +++ b/frameworks/wmtest/test/wmclient_native_test_35.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021 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 "wmclient_native_test_35.h" + +#include +#include +#include + +#include +#include +#include + +#include "inative_test.h" +#include "native_test_class.h" +#include "util.h" + +using namespace OHOS; + +namespace { +constexpr int32_t DISPLAY_MODE_SINGLE = 1; +constexpr int32_t DISPLAY_MODE_CLONE = 2; +constexpr int32_t DISPLAY_MODE_EXTEND = 3; +constexpr int32_t DISPLAY_MODE_EXPAND = 4; +class WMClientNativeTest35 : public INativeTest { +public: + std::string GetDescription() const + { + constexpr const char *desc = "set display mode"; + return desc; + } + + std::string GetDomain() const + { + constexpr const char *desc = "wmclient"; + return desc; + } + + int32_t GetID() const + { + constexpr int32_t id = 35; + return id; + } + + uint32_t GetLastTime() const + { + constexpr uint32_t lastTime = 1000; + return lastTime; + } + + void inputExplain() + { + printf("please input set display mode: wmtest wmclient 35 [parameter] \n"); + printf("[parameter] : 1 , 2 , 3 , 4 \n"); + printf("1 : set display mode to SINGLE \n"); + printf("2 : set display mode to CLONE\n"); + printf("3 : set display mode to EXTEND\n"); + printf("4 : set display mode to EXPAND\n"); + } + + void Run(int32_t argc, const char **argv) + { + OptionParser parser; + int32_t displayMode = 0; + parser.AddArguments(displayMode); + if (parser.Parse(argc, argv)) { + std::cerr << parser.GetErrorString() << std::endl; + inputExplain(); + ExitTest(); + return; + } + + auto wm = WindowManager::GetInstance(); + auto wmRet = wm->Init(); + if (wmRet) { + printf("init failed with %s\n", WMErrorStr(wmRet).c_str()); + ExitTest(); + return; + } + + switch (displayMode) { + case DISPLAY_MODE_SINGLE: + wmRet = wm->SetDisplayMode(WM_DISPLAY_MODE_SINGLE); + printf("1 : set display mode to SINGLE \n"); + break; + case DISPLAY_MODE_CLONE: + wmRet = wm->SetDisplayMode(WM_DISPLAY_MODE_CLONE); + printf("2 : set display mode to CLONE\n"); + break; + case DISPLAY_MODE_EXTEND: + wmRet = wm->SetDisplayMode(WM_DISPLAY_MODE_EXTEND); + printf("3 : set display mode to EXTEND\n"); + break; + case DISPLAY_MODE_EXPAND: + wmRet = wm->SetDisplayMode(WM_DISPLAY_MODE_EXPAND); + printf("4 : set display mode to EXPAND\n"); + break; + default: + inputExplain(); + return; + break; + } + + if (wmRet != WM_OK) { + printf("set display mode failed with %s.\n", WMErrorStr(wmRet).c_str()); + ExitTest(); + return; + } + + printf("set display mode succeed.\n"); + } +private: + sptr window; + sptr windowSync; +} g_autoload; +} // namespace diff --git a/frameworks/wmtest/test/wmclient_native_test_35.h b/frameworks/wmtest/test/wmclient_native_test_35.h new file mode 100644 index 0000000000..e668c3c7ec --- /dev/null +++ b/frameworks/wmtest/test/wmclient_native_test_35.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_WMTEST_TEST_WMCLIENT_WMCLIENT_NATIVE_TEST_35_H +#define FRAMEWORKS_WMTEST_TEST_WMCLIENT_WMCLIENT_NATIVE_TEST_35_H + +#endif // FRAMEWORKS_WMTEST_TEST_WMCLIENT_WMCLIENT_NATIVE_TEST_35_H diff --git a/graphic.cfg b/graphic.cfg index 08b840251d..836d1a670e 100644 --- a/graphic.cfg +++ b/graphic.cfg @@ -2,11 +2,16 @@ "jobs" : [{ "name" : "weston_start", "cmds" : [ + "start graphic_dumper_server", "start bootanimation" ] } ], "services" : [{ + "name" : "graphic_dumper_server", + "path" : ["/system/bin/graphic_dumper_server"], + "disabled" : 1 + }, { "name" : "vsync_server", "path" : ["/system/bin/vsync_server"], "disabled" : 1 diff --git a/graphic.rc b/graphic.rc index d89540aded..c05afeafb7 100644 --- a/graphic.rc +++ b/graphic.rc @@ -16,10 +16,16 @@ service vsync_server /system/bin/vsync_server disabled seclabel u:r:wms_service:s0 +service graphic_dumper_server /system/bin/graphic_dumper_server + class weston + disabled + seclabel u:r:wms_service:s0 + service bootanimation /system/bin/bootanimation class weston disabled oneshot on weston_start + start graphic_dumper_server start bootanimation diff --git a/interfaces/innerkits/dumper/graphic_dumper_helper.h b/interfaces/innerkits/dumper/graphic_dumper_helper.h new file mode 100644 index 0000000000..98cb70f81d --- /dev/null +++ b/interfaces/innerkits/dumper/graphic_dumper_helper.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 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 FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_HELPER_H +#define FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_HELPER_H + +#include "graphic_common.h" + +#ifdef __cplusplus +#include + +namespace OHOS { +using OnConfigChangeFunc = std::function; +using OnDumpFunc = std::function; +class GraphicDumperHelper : public RefBase { +public: + static sptr GetInstance(); + virtual GSError SendInfo(const std::string &tag, const char *fmt, ...) = 0; + + virtual int32_t AddConfigChangeListener(const std::string &tag, OnConfigChangeFunc func) = 0; + virtual GSError RemoveConfigChangeListener(const int32_t listenerId) = 0; + virtual int32_t AddDumpListener(const std::string &tag, OnDumpFunc func) = 0; + virtual GSError RemoveDumpListener(const int32_t listenerId) = 0; +}; +} // namespace OHOS + +extern "C" { +#endif + +typedef void(*OnDumpFuncPtr)(void); +typedef void(*OnConfigChangeFuncPtr)(const char *, const char *); + +int SendInfo(const char* tag, const char *fmt, ...); +int AddConfigChangeListener(const char* tag, OnConfigChangeFuncPtr func); +int RemoveConfigChangeListener(int listenerId); +int AddDumpListener(const char* tag, OnDumpFuncPtr func); +int RemoveDumpListener(int listenerId); + +#ifdef __cplusplus +} +#endif + +#endif // FRAMEWORKS_DUMPRE_INCLUDE_GRAPHIC_DUMPER_HELPER_H diff --git a/interfaces/innerkits/wmclient/virtual_display_option.h b/interfaces/innerkits/wmclient/virtual_display_option.h new file mode 100644 index 0000000000..58c3b853c0 --- /dev/null +++ b/interfaces/innerkits/wmclient/virtual_display_option.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 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 INTERFACES_INNERKITS_WMCLIENT_VIRTUAL_DISPLAY_OPTION_H +#define INTERFACES_INNERKITS_WMCLIENT_VIRTUAL_DISPLAY_OPTION_H + +#include +#include + +#include "window_manager_type.h" + +namespace OHOS { +class VirtualDisplayOption : public RefBase { +public: + static sptr Get(); + + virtual WMError SetX(int32_t x) = 0; + virtual WMError SetY(int32_t y) = 0; + virtual WMError SetWidth(uint32_t width) = 0; + virtual WMError SetHeight(uint32_t height) = 0; + + virtual int32_t GetX() const = 0; + virtual int32_t GetY() const = 0; + virtual uint32_t GetWidth() const = 0; + virtual uint32_t GetHeight() const = 0; + + virtual bool IsSettingX() const = 0; + virtual bool IsSettingY() const = 0; + virtual bool IsSettingWidth() const = 0; + virtual bool IsSettingHeight() const = 0; +}; +} // namespace OHOS + +#endif // INTERFACES_INNERKITS_WMCLIENT_VIRTUAL_DISPLAY_OPTION_H diff --git a/interfaces/innerkits/wmclient/window_manager.h b/interfaces/innerkits/wmclient/window_manager.h index d8e9389d28..700209f33a 100644 --- a/interfaces/innerkits/wmclient/window_manager.h +++ b/interfaces/innerkits/wmclient/window_manager.h @@ -27,6 +27,7 @@ #include "window.h" #include "window_manager_type.h" #include "window_option.h" +#include "virtual_display_option.h" namespace OHOS { class WindowManager : public RefBase { @@ -45,6 +46,10 @@ public: virtual WMError ListenNextScreenShot(int32_t id, IScreenShotCallback *cb) = 0; virtual WMError ListenNextWindowShot(const sptr &window, IWindowShotCallback *cb) = 0; + + virtual WMError CreateVirtualDisplay(const sptr &option) = 0; + virtual WMError DestroyVirtualDisplay(uint32_t did) = 0; + virtual WMError SetDisplayMode(WMSDisplayMode mode) = 0; }; } // namespace OHOS diff --git a/interfaces/innerkits/wmclient/window_manager_type.h b/interfaces/innerkits/wmclient/window_manager_type.h index 6eae7571d5..5a5023847f 100644 --- a/interfaces/innerkits/wmclient/window_manager_type.h +++ b/interfaces/innerkits/wmclient/window_manager_type.h @@ -54,6 +54,19 @@ enum WindowMode { WINDOW_MODE_MAX, }; +// bitmask +enum WMSDisplayMode { + WM_DISPLAY_MODE_SINGLE = 1, + WM_DISPLAY_MODE_CLONE = 2, + WM_DISPLAY_MODE_EXTEND = 4, + WM_DISPLAY_MODE_EXPAND = 8, +}; + +enum DisplayType { + DISPLAY_TYPE_PHYSICAL = 0, + DISPLAY_TYPE_VIRTUAL, + DISPLAY_TYPE_MAX, +}; struct WMDisplayInfo { int32_t id; uint32_t width; @@ -61,6 +74,7 @@ struct WMDisplayInfo { uint32_t phyWidth; uint32_t phyHeight; uint32_t vsync; + enum DisplayType type; }; #ifdef __cplusplus diff --git a/interfaces/innerkits/wmservice/iwindow_manager_service.h b/interfaces/innerkits/wmservice/iwindow_manager_service.h index 15843af486..a2d3ace46d 100644 --- a/interfaces/innerkits/wmservice/iwindow_manager_service.h +++ b/interfaces/innerkits/wmservice/iwindow_manager_service.h @@ -60,6 +60,9 @@ public: virtual sptr ScaleTo(int32_t wid, uint32_t width, uint32_t height) = 0; virtual sptr SetWindowType(int32_t wid, WindowType type) = 0; virtual sptr SetWindowMode(int32_t wid, WindowMode mode) = 0; + + virtual sptr CreateVirtualDisplay(int32_t x, int32_t y, int32_t width, int32_t height) = 0; + virtual sptr DestroyVirtualDisplay(uint32_t did) = 0; }; } // namespace OHOS diff --git a/interfaces/innerkits/wmservice/window_manager_service_type.h b/interfaces/innerkits/wmservice/window_manager_service_type.h index 4960f742e8..7d0f22cd2e 100644 --- a/interfaces/innerkits/wmservice/window_manager_service_type.h +++ b/interfaces/innerkits/wmservice/window_manager_service_type.h @@ -23,14 +23,6 @@ #include namespace OHOS { -// bitmask -enum WMSDisplayMode { - WM_DISPLAY_MODE_SINGLE = 1, - WM_DISPLAY_MODE_CLONE = 2, - WM_DISPLAY_MODE_EXTEND = 4, - WM_DISPLAY_MODE_EXPAND = 8, -}; - enum WMSDisplayDirection { WMS_DISPLAY_DIRECTION_DOWN = 0, WMS_DISPLAY_DIRECTION_LEFT = 1, diff --git a/ohos.build b/ohos.build index f36aab3212..5f8b99ada8 100755 --- a/ohos.build +++ b/ohos.build @@ -6,6 +6,10 @@ "//foundation/graphic/standard/interfaces/kits/js/declaration:window", "//foundation/graphic/standard/interfaces/kits/napi:napi_packages", + "//foundation/graphic/standard/frameworks/dumper:gdumper.ini", + "//foundation/graphic/standard/frameworks/dumper:graphic_dumper_server", + "//foundation/graphic/standard/frameworks/dumper:gdumper", + "//third_party/wayland-ivi-extension:ivi-controller", "//third_party/wayland-ivi-extension:ivi-input-controller", "//third_party/wayland-ivi-extension:libscreen-info-module", diff --git a/utils/BUILD.gn b/utils/BUILD.gn index 0431cb5a9f..65d8bac093 100644 --- a/utils/BUILD.gn +++ b/utils/BUILD.gn @@ -26,3 +26,7 @@ group("semaphore") { group("test_header") { public_deps = [ "test_header:test_header" ] } + +group("option_parser") { + public_deps = [ "option_parser:option_parser" ] +} diff --git a/utils/option_parser/BUILD.gn b/utils/option_parser/BUILD.gn new file mode 100644 index 0000000000..68e8833d4c --- /dev/null +++ b/utils/option_parser/BUILD.gn @@ -0,0 +1,41 @@ +# Copyright (c) 2021 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") + +## Build option_parser.so {{{ +config("option_parser_config") { + visibility = [ ":*" ] + + cflags = [ + "-Wall", + "-Werror", + "-g3", + ] +} + +config("option_parser_public_config") { + include_dirs = [ "export" ] +} + +ohos_shared_library("option_parser") { + sources = [ "src/option_parser.cpp" ] + + configs = [ ":option_parser_config" ] + + public_configs = [ ":option_parser_public_config" ] + + subsystem_name = "graphic" + part_name = "graphic_standard" +} +## Build option_parser.so }}} diff --git a/utils/option_parser/export/option_parser.h b/utils/option_parser/export/option_parser.h new file mode 100644 index 0000000000..a28e435562 --- /dev/null +++ b/utils/option_parser/export/option_parser.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2021 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 UTILS_OPTION_PARSER_EXPORT_OPTION_PARSER_H +#define UTILS_OPTION_PARSER_EXPORT_OPTION_PARSER_H + +#include +#include +#include +#include + +class OptionParser { +public: + int32_t Parse(int32_t argc, const char **argv); + std::string GetErrorString(); + + template + int32_t AddOption(const std::string &shortOpt, const std::string &longOpt, T &result) + { + assert(!"not support"); + return 0; + } + + template<> + int32_t AddOption(const std::string &shortOpt, const std::string &longOpt, int32_t &result) + { + return AddOption(shortOpt, longOpt, &result, Option::ValueType::i32); + } + + template<> + int32_t AddOption(const std::string &shortOpt, const std::string &longOpt, int64_t &result) + { + return AddOption(shortOpt, longOpt, &result, Option::ValueType::i64); + } + + template<> + int32_t AddOption(const std::string &shortOpt, const std::string &longOpt, double &result) + { + return AddOption(shortOpt, longOpt, &result, Option::ValueType::f64); + } + + template<> + int32_t AddOption(const std::string &shortOpt, const std::string &longOpt, std::string &result) + { + return AddOption(shortOpt, longOpt, &result, Option::ValueType::str); + } + + template<> + int32_t AddOption(const std::string &shortOpt, const std::string &longOpt, bool &result) + { + return AddOption(shortOpt, longOpt, &result, Option::ValueType::bol); + } + + template + int32_t AddArguments(T &result) + { + assert(!"not support"); + return 0; + } + + template<> + int32_t AddArguments(int32_t &result) + { + return AddArguments(&result, Argument::ValueType::i32); + } + + template<> + int32_t AddArguments(int64_t &result) + { + return AddArguments(&result, Argument::ValueType::i64); + } + + template<> + int32_t AddArguments(double &result) + { + return AddArguments(&result, Argument::ValueType::f64); + } + + template<> + int32_t AddArguments(std::string &result) + { + return AddArguments(&result, Argument::ValueType::str); + } + + int32_t GetSkippedArgc(); + const char **GetSkippedArgv(); + +private: + int32_t ParseArgument(const char *arg, const char *arg2); + int32_t ParseArgc(const char *arg, const char *arg2); + int32_t ParseShortOption(const char *arg1, const char *arg2); + int32_t ParseLongEqualOption(const char *arg, const char *arg2); + int32_t ParseLongOption(const char *arg1, const char *arg2); + int32_t AddSkipped(const char *arg, const char *arg2); + + struct Option { + const std::string so; + const std::string lo; + union Value { + int32_t i32; + int64_t i64; + double f64; + std::string str; + bool bl; + } *result; + enum class ValueType { + i32, + i64, + f64, + str, + bol, + } type; + }; + + int32_t AddOption(const std::string &shortOpt, + const std::string &longOpt, void *result, Option::ValueType type); + + struct Argument { + union Value { + int32_t i32; + int64_t i64; + double f64; + std::string str; + } *result; + enum class ValueType { + i32, + i64, + f64, + str, + } type; + }; + + int32_t AddArguments(void *result, Argument::ValueType type); + + std::list arguments; + std::vector options; + std::vector skipped; + std::string error = ""; +}; + +#endif // UTILS_OPTION_PARSER_EXPORT_OPTION_PARSER_H diff --git a/utils/option_parser/src/option_parser.cpp b/utils/option_parser/src/option_parser.cpp new file mode 100644 index 0000000000..e80b5a512b --- /dev/null +++ b/utils/option_parser/src/option_parser.cpp @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2021 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 + +enum { + PARSER_NEXT = 0, + PARSER_ERROR = 1, + PARSER_PARSED = 2, + PARSER_PARSED_MORE = 3, +}; + +int32_t OptionParser::ParseArgument(const char *arg, const char *arg2) +{ + if (arguments.empty()) { + return PARSER_NEXT; + } + + std::stringstream ss(arg); + switch (arguments.front().type) { + case Argument::ValueType::i32: + ss >> arguments.front().result->i32; + break; + case Argument::ValueType::i64: + ss >> arguments.front().result->i64; + break; + case Argument::ValueType::f64: + ss >> arguments.front().result->f64; + break; + case Argument::ValueType::str: + ss >> arguments.front().result->str; + break; + } + + if (!ss.eof() || !ss) { + error = "parse "; + error = error + arg + " error"; + return PARSER_ERROR; + } + + arguments.pop_front(); + return PARSER_PARSED; +} + +int32_t OptionParser::ParseArgc(const char *arg, const char *arg2) +{ + if (arg[0] == 0) { + return PARSER_ERROR; + } + + if (arg[0] != '-') { + skipped.push_back(arg); + return PARSER_PARSED; + } + + if (arg[1] == 0) { + return PARSER_ERROR; + } + return PARSER_NEXT; +} + +int32_t OptionParser::ParseShortOption(const char *arg1, const char *arg2) +{ + if (arg1[1] == '-') { + // long option + return PARSER_NEXT; + } + + for (const auto &option : options) { + if (option.so == &arg1[1]) { + if (option.type == Option::ValueType::bol) { + option.result->bl = !option.result->bl; + return PARSER_PARSED; + } else if (arg2 == nullptr) { + error = option.so + " need argument"; + return PARSER_ERROR; + } + + std::stringstream ss(arg2); + switch (option.type) { + case Option::ValueType::i32: + ss >> option.result->i32; + break; + case Option::ValueType::i64: + ss >> option.result->i64; + break; + case Option::ValueType::f64: + ss >> option.result->f64; + break; + case Option::ValueType::str: + ss >> option.result->str; + break; + default: + assert(!"no way"); + break; + } + + if (!ss.eof() || !ss) { + error = "parse "; + error = error + arg1 + " error, " + arg2; + return PARSER_ERROR; + } + + return PARSER_PARSED_MORE; + } + } + return PARSER_NEXT; +} + +int32_t OptionParser::ParseLongEqualOption(const char *arg, const char *arg2) +{ + if (arg[1] != '-') { + return PARSER_NEXT; + } + + int32_t ret = 0; + bool parsed = false; + for (const char *c = arg; *c; c++) { + if (*c == '=') { + std::string arg1(arg, c - arg); + std::string arg2(c + 1); + ret = ParseLongOption(arg1.c_str(), arg2.c_str()); + parsed = true; + break; + } + } + + if (ret == PARSER_ERROR || ret == PARSER_NEXT) { + return ret; + } + + if (parsed) { + return PARSER_PARSED; + } + return PARSER_NEXT; +} + +int32_t OptionParser::ParseLongOption(const char *arg1, const char *arg2) +{ + if (arg1[1] != '-') { + return PARSER_NEXT; + } + + for (const auto &option : options) { + if (option.lo == &arg1[0x2]) { + if (option.type == Option::ValueType::bol) { + option.result->bl = !option.result->bl; + return PARSER_PARSED; + } else if (arg2 == nullptr) { + error = option.lo + " need argument"; + return PARSER_ERROR; + } + + std::stringstream ss(arg2); + switch (option.type) { + case Option::ValueType::i32: + ss >> option.result->i32; + break; + case Option::ValueType::i64: + ss >> option.result->i64; + break; + case Option::ValueType::f64: + ss >> option.result->f64; + break; + case Option::ValueType::str: + ss >> option.result->str; + break; + default: + assert(!"no way"); + break; + } + + if (!ss.eof() || !ss) { + error = "parse "; + error = error + arg1 + " error, " + arg2; + return PARSER_ERROR; + } + return PARSER_PARSED_MORE; + } + } + return PARSER_NEXT; +} + +int32_t OptionParser::AddSkipped(const char *arg, const char *arg2) +{ + skipped.push_back(arg); + return PARSER_PARSED; +} + +int32_t OptionParser::Parse(int32_t argc, const char **argv) +{ + int32_t (OptionParser:: *parsers[])(const char *, const char *) = { + &OptionParser::ParseArgument, + &OptionParser::ParseArgc, + &OptionParser::ParseShortOption, + &OptionParser::ParseLongEqualOption, + &OptionParser::ParseLongOption, + &OptionParser::AddSkipped, + }; + for (int32_t i = 0; i < argc; i++) { + for (auto &parser : parsers) { + auto ret = (this->*parser)(argv[i], argv[i + 1]); + if (ret == PARSER_ERROR) { + return ret; + } else if (ret == PARSER_PARSED_MORE) { + i++; + break; + } else if (ret == PARSER_PARSED) { + break; + } + } + } + + if (!arguments.empty()) { + error = "need more arguments"; + return 1; + } else { + skipped.push_back(nullptr); + } + + return 0; +} + +int32_t OptionParser::AddOption(const std::string &shortOpt, + const std::string &longOpt, void *result, Option::ValueType type) +{ + struct Option option = { + .so = shortOpt, + .lo = longOpt, + .result = reinterpret_cast(result), + .type = type, + }; + options.emplace_back(std::move(option)); + return 0; +} + +int32_t OptionParser::AddArguments(void *result, Argument::ValueType type) +{ + struct Argument argument = { + .result = reinterpret_cast(result), + .type = type, + }; + arguments.emplace_back(std::move(argument)); + return 0; +} + +std::string OptionParser::GetErrorString() +{ + return error; +} + +int32_t OptionParser::GetSkippedArgc() +{ + return skipped.size() - 1; +} + +const char **OptionParser::GetSkippedArgv() +{ + return skipped.data(); +}