From d7cb96daf002bf591f12059d903c164bdea1d16a Mon Sep 17 00:00:00 2001 From: "zhangyafei.echo" Date: Wed, 29 Nov 2023 16:10:18 +0800 Subject: [PATCH] Description:Add connect uiextension moduletest. Sig:SIG_ApplicationFramework Feature or BugFix: Feature Binary Source: No Signed-off-by: zhangyafei.echo Change-Id: I3f866ac60b9cf5de24236ef88465ae688a621352 --- test/moduletest/BUILD.gn | 1 + .../ui_extension_ability_test/BUILD.gn | 22 + .../ohos_test/BUILD.gn | 21 + .../ohos_test/ohos_test.xml | 28 + .../ui_extension_connect_module_test/BUILD.gn | 63 ++ .../ui_extension_connect_module_test.cpp | 646 ++++++++++++++++++ ...tension_connect_module_test_connection.cpp | 39 ++ ...extension_connect_module_test_connection.h | 40 ++ ...extension_connect_module_test_observer.cpp | 72 ++ ...i_extension_connect_module_test_observer.h | 44 ++ .../AppScope/app.json | 12 + .../resources/base/element/string.json | 8 + .../resources/base/media/app_icon.png | Bin 0 -> 6790 bytes .../ui_extension_provider_bundle/BUILD.gn | 51 ++ .../main/ets/IdlServiceExt/IIdlServiceExt.idl | 19 + .../ets/IdlServiceExt/i_idl_service_ext.ts | 21 + .../ets/IdlServiceExt/idl_service_ext_impl.ts | 36 + .../IdlServiceExt/idl_service_ext_proxy.ts | 68 ++ .../ets/IdlServiceExt/idl_service_ext_stub.ts | 60 ++ .../main/ets/entryability/EntryAbility.ets | 58 ++ .../entry/src/main/ets/pages/Extension.ets | 83 +++ .../entry/src/main/ets/pages/Index.ets | 32 + .../uiextensionability/UIExtensionAbility.ets | 61 ++ .../entry/src/main/module.json | 48 ++ .../main/resources/base/element/color.json | 8 + .../main/resources/base/element/string.json | 24 + .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../main/resources/base/media/startIcon.png | Bin 0 -> 6790 bytes .../resources/base/profile/main_pages.json | 6 + .../signature/openharmony_sx.p7b | Bin 0 -> 3429 bytes .../AppScope/app.json | 12 + .../resources/base/element/string.json | 8 + .../resources/base/media/app_icon.png | Bin 0 -> 6790 bytes .../ui_extension_user_bundle/BUILD.gn | 51 ++ .../main/ets/entryability/EntryAbility.ets | 58 ++ .../entry/src/main/ets/pages/Index.ets | 75 ++ .../entry/src/main/module.json | 38 ++ .../main/resources/base/element/color.json | 8 + .../main/resources/base/element/string.json | 16 + .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../main/resources/base/media/startIcon.png | Bin 0 -> 6790 bytes .../resources/base/profile/main_pages.json | 5 + .../signature/openharmony_sx.p7b | Bin 0 -> 3426 bytes 43 files changed, 1842 insertions(+) create mode 100644 test/moduletest/ui_extension_ability_test/BUILD.gn create mode 100644 test/moduletest/ui_extension_ability_test/ohos_test/BUILD.gn create mode 100644 test/moduletest/ui_extension_ability_test/ohos_test/ohos_test.xml create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/BUILD.gn create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test.cpp create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test_connection.cpp create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test_connection.h create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test_observer.cpp create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test_observer.h create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/AppScope/app.json create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/AppScope/resources/base/element/string.json create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/AppScope/resources/base/media/app_icon.png create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/BUILD.gn create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/IdlServiceExt/IIdlServiceExt.idl create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/IdlServiceExt/i_idl_service_ext.ts create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/IdlServiceExt/idl_service_ext_impl.ts create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/IdlServiceExt/idl_service_ext_proxy.ts create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/IdlServiceExt/idl_service_ext_stub.ts create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/entryability/EntryAbility.ets create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/pages/Extension.ets create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/pages/Index.ets create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/uiextensionability/UIExtensionAbility.ets create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/module.json create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/resources/base/element/color.json create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/resources/base/element/string.json create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/resources/base/media/icon.png create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/resources/base/media/startIcon.png create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/resources/base/profile/main_pages.json create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/signature/openharmony_sx.p7b create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/AppScope/app.json create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/AppScope/resources/base/element/string.json create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/AppScope/resources/base/media/app_icon.png create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/BUILD.gn create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/ets/entryability/EntryAbility.ets create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/ets/pages/Index.ets create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/module.json create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/resources/base/element/color.json create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/resources/base/element/string.json create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/resources/base/media/icon.png create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/resources/base/media/startIcon.png create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/resources/base/profile/main_pages.json create mode 100644 test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/signature/openharmony_sx.p7b diff --git a/test/moduletest/BUILD.gn b/test/moduletest/BUILD.gn index d50ce1f1067..bc24f05dd45 100644 --- a/test/moduletest/BUILD.gn +++ b/test/moduletest/BUILD.gn @@ -64,6 +64,7 @@ group("moduletest") { "quick_fix:moduletest", "running_infos_module_test:moduletest", "start_option_display_id_test:moduletest", + "ui_extension_ability_test:moduletest", "//third_party/icu/icu4c:shared_icuuc", "//third_party/jsoncpp:jsoncpp", ] diff --git a/test/moduletest/ui_extension_ability_test/BUILD.gn b/test/moduletest/ui_extension_ability_test/BUILD.gn new file mode 100644 index 00000000000..625a69c20eb --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/BUILD.gn @@ -0,0 +1,22 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +group("moduletest") { + testonly = true + + deps = [ + "ui_extension_connect_module_test:moduletest", + "ui_extension_provider_bundle:assisthap", + "ui_extension_user_bundle:assisthap", + ] +} diff --git a/test/moduletest/ui_extension_ability_test/ohos_test/BUILD.gn b/test/moduletest/ui_extension_ability_test/ohos_test/BUILD.gn new file mode 100644 index 00000000000..7b7ae726679 --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ohos_test/BUILD.gn @@ -0,0 +1,21 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +ohos_copy("copy_ohos_test") { + subsystem_name = "ability" + part_name = "ability_runtime" + sources = [ "./ohos_test.xml" ] + outputs = [ "$root_out_dir/tests/moduletest/ability_runtime/ui_extension/resource/ohos_test.xml" ] +} diff --git a/test/moduletest/ui_extension_ability_test/ohos_test/ohos_test.xml b/test/moduletest/ui_extension_ability_test/ohos_test/ohos_test.xml new file mode 100644 index 00000000000..80067a7d98c --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ohos_test/ohos_test.xml @@ -0,0 +1,28 @@ + + + + + + + + diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/BUILD.gn b/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/BUILD.gn new file mode 100644 index 00000000000..8c06a8e40be --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//build/test.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_moduletest("ui_extension_connect_module_test") { + module_out_path = "ability_runtime/ui_extension" + + sources = [ + "ui_extension_connect_module_test.cpp", + "ui_extension_connect_module_test_connection.cpp", + "ui_extension_connect_module_test_observer.cpp", + ] + + configs = [ "${ability_runtime_services_path}/common:common_config" ] + + cflags = [] + + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${ability_runtime_path}/test/moduletest/ui_extension_ability_test/ohos_test:copy_ohos_test", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + ] + + external_deps = [ + "ability_base:session_info", + "ability_base:want", + "ability_runtime:ability_manager", + "ability_runtime:app_manager", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "ffrt:libffrt", + "hilog:libhilog", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] +} + +group("moduletest") { + testonly = true + deps = [ ":ui_extension_connect_module_test" ] +} diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test.cpp b/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test.cpp new file mode 100644 index 00000000000..8e635c976ad --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test.cpp @@ -0,0 +1,646 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "ability_manager_client.h" +#include "ability_util.h" +#include "accesstoken_kit.h" +#include "app_mgr_interface.h" +#include "hilog_wrapper.h" +#include "nativetoken_kit.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "session_info.h" +#include "system_ability_definition.h" +#include "token_setproc.h" +#include "ui_extension_connect_module_test_connection.h" +#include "ui_extension_connect_module_test_observer.h" +#include "want.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace AAFwk { +namespace { +const int CONNECT_TIMEOUT_MS = 5 * 1000; +const int32_t MAIN_USER_ID = 100; + +const std::string TARGET_BUNDLE_NAME = "com.ohos.uiextensionprovider"; +const std::string TARGET_ABILITY_NAME = "UIExtensionProvider"; +const std::string TARGET_MODULE_NAME = "entry"; + +const std::string USER_BUNDLE_NAME = "com.ohos.uiextensionuser"; +const std::string USER_ABILITY_NAME = "EntryAbility"; +const std::string USER_MODULE_NAME = "entry"; + +static void SetNativeToken() +{ + uint64_t tokenId; + const char **perms = new const char *[2]; + perms[0] = "ohos.permission.CONNECT_UI_EXTENSION_ABILITY"; + perms[1] = "ohos.permission.RUNNING_STATE_OBSERVER"; + NativeTokenInfoParams infoInstance = { + .dcapsNum = 0, + .permsNum = 2, + .aclsNum = 0, + .dcaps = nullptr, + .perms = perms, + .acls = nullptr, + .aplStr = "system_core", + }; + + infoInstance.processName = "SetUpTestCase"; + tokenId = GetAccessTokenId(&infoInstance); + SetSelfTokenID(tokenId); + OHOS::Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo(); + delete[] perms; +} +} // namespace + +using IAbilityConnection = AppExecFwk::IAbilityConnection; +using IApplicationStateObserver = AppExecFwk::IApplicationStateObserver; + +class UIExtensionConnectModuleTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + void WaitUntilConnectDone(const sptr &connection); + void WaitUntilDisConnectDone(const sptr &connection); + void WaitUntilProcessCreated(const sptr &observer); + void WaitUntilProcessDied(const sptr &observer); + void WaitUntilAbilityForeground(const sptr &observer); + void WaitUntilAbilityBackground(const sptr &observer); + + void RegisterApplicationStateObserver(const sptr &observer); + void UnregisterApplicationStateObserver(const sptr &observer); + static sptr appMgr_; +}; + +sptr UIExtensionConnectModuleTest::appMgr_ = nullptr; + +void UIExtensionConnectModuleTest::SetUpTestCase(void) +{ + auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemAbilityMgr == nullptr) { + HILOG_ERROR("Failed to get SystemAbilityManager."); + return; + } + + auto remoteObj = systemAbilityMgr->GetSystemAbility(APP_MGR_SERVICE_ID); + if (remoteObj == nullptr) { + HILOG_ERROR("Remote object is nullptr."); + return; + } + + sptr appMgr = iface_cast(remoteObj); + if (appMgr == nullptr) { + HILOG_ERROR("App mgr is nullptr."); + return; + } + + appMgr_ = appMgr; +} + +void UIExtensionConnectModuleTest::TearDownTestCase(void) +{} + +void UIExtensionConnectModuleTest::SetUp() +{} + +void UIExtensionConnectModuleTest::TearDown() +{} + +void UIExtensionConnectModuleTest::RegisterApplicationStateObserver(const sptr &observer) +{ + std::vector bundleNameList; + bundleNameList.push_back(TARGET_BUNDLE_NAME); + bundleNameList.push_back(USER_BUNDLE_NAME); + auto ret = appMgr_->RegisterApplicationStateObserver(observer, bundleNameList); + if (ret != ERR_OK) { + HILOG_ERROR("Register failed."); + } +} + +void UIExtensionConnectModuleTest::UnregisterApplicationStateObserver(const sptr &observer) +{ + auto ret = appMgr_->UnregisterApplicationStateObserver(observer); + if (ret != ERR_OK) { + HILOG_ERROR("Unregister failed."); + } +} + +void UIExtensionConnectModuleTest::WaitUntilConnectDone(const sptr &connection) +{ + std::unique_lock lock(connection->connectMutex_); + auto waitStatus = connection->connectCondation_.wait_for(lock, std::chrono::milliseconds(CONNECT_TIMEOUT_MS), + [connection]() { + return connection->connectFinished_; + }); + EXPECT_EQ(waitStatus, true); + EXPECT_EQ(connection->connectFinished_, true); +} + +void UIExtensionConnectModuleTest::WaitUntilDisConnectDone( + const sptr &connection) +{ + std::unique_lock lock(connection->connectMutex_); + auto waitStatus = connection->connectCondation_.wait_for(lock, std::chrono::milliseconds(CONNECT_TIMEOUT_MS), + [connection]() { + return connection->disConnectFinished_; + }); + EXPECT_EQ(waitStatus, true); + EXPECT_EQ(connection->disConnectFinished_, true); +} + +void UIExtensionConnectModuleTest::WaitUntilProcessCreated(const sptr &observer) +{ + std::unique_lock lock(observer->observerMutex_); + auto waitStatus = observer->observerCondation_.wait_for(lock, std::chrono::milliseconds(CONNECT_TIMEOUT_MS), + [observer]() { + return observer->processCreated_; + }); + EXPECT_EQ(waitStatus, true); + EXPECT_EQ(observer->processCreated_, true); +} + +void UIExtensionConnectModuleTest::WaitUntilProcessDied(const sptr &observer) +{ + std::unique_lock lock(observer->observerMutex_); + auto waitStatus = observer->observerCondation_.wait_for(lock, std::chrono::milliseconds(CONNECT_TIMEOUT_MS), + [observer]() { + return observer->processDied_; + }); + EXPECT_EQ(waitStatus, true); + EXPECT_EQ(observer->processDied_, true); +} + +void UIExtensionConnectModuleTest::WaitUntilAbilityForeground( + const sptr &observer) +{ + std::unique_lock lock(observer->observerMutex_); + auto waitStatus = observer->observerCondation_.wait_for(lock, std::chrono::milliseconds(CONNECT_TIMEOUT_MS), + [observer]() { + return observer->processForegrounded_; + }); + EXPECT_EQ(waitStatus, true); + EXPECT_EQ(observer->processForegrounded_, true); +} + +void UIExtensionConnectModuleTest::WaitUntilAbilityBackground( + const sptr &observer) +{ + std::unique_lock lock(observer->observerMutex_); + auto waitStatus = observer->observerCondation_.wait_for(lock, std::chrono::milliseconds(CONNECT_TIMEOUT_MS), + [observer]() { + return observer->processBackgrounded_; + }); + EXPECT_EQ(waitStatus, true); + EXPECT_EQ(observer->processBackgrounded_, true); +} + +/** + * @tc.name: ConnectUIExtensionAbility_0100 + * @tc.desc: basic function test. + * @tc.type: FUNC + * @tc.require: issueI5OD2E + */ +HWTEST_F(UIExtensionConnectModuleTest, ConnectUIExtensionAbility_0100, TestSize.Level1) +{ + HILOG_INFO("start."); + + auto currentId = GetSelfTokenID(); + SetNativeToken(); + + auto observer = sptr::MakeSptr(); + RegisterApplicationStateObserver(observer); + + Want providerWant; + AppExecFwk::ElementName providerElement("0", TARGET_BUNDLE_NAME, TARGET_ABILITY_NAME, TARGET_MODULE_NAME); + providerWant.SetElement(providerElement); + + auto connection = sptr::MakeSptr(); + ASSERT_NE(connection, nullptr); + + auto sessionInfo = sptr::MakeSptr(); + ASSERT_NE(sessionInfo, nullptr); + + // Connect ui extension ability firstly. + auto connectInfo = sptr::MakeSptr(); + ASSERT_NE(connectInfo, nullptr); + connectInfo->hostBundleName = USER_BUNDLE_NAME; + connectInfo->uiExtensionAbilityId = 0; + auto ret = AbilityManagerClient::GetInstance()->ConnectUIExtensionAbility(providerWant, connection, sessionInfo, + DEFAULT_INVAL_VALUE, connectInfo); + EXPECT_EQ(ret, ERR_OK); + HILOG_INFO("UIExtensonAbility id %{public}d", connectInfo->uiExtensionAbilityId); + EXPECT_NE(connectInfo->uiExtensionAbilityId, 0); + + // Wait until OnAbilityConnectDone has triggered. + WaitUntilConnectDone(connection); + + // Send uiextensionability id to ui extension user + // start ui extension user + Want userWant; + AppExecFwk::ElementName userElement("0", USER_BUNDLE_NAME, USER_ABILITY_NAME, USER_MODULE_NAME); + userWant.SetElement(userElement); + ret = AbilityManagerClient::GetInstance()->StartAbility(userWant); + EXPECT_EQ(ret, ERR_OK); + + // Wait until ability has foregrounded + WaitUntilAbilityForeground(observer); + + // Disconnect ui extension ability. + // wish can't be destroyed, cause there exist ui extension component. + ret = AbilityManagerClient::GetInstance()->DisconnectAbility(connection); + EXPECT_EQ(ret, ERR_OK); + + // Wait until OnAbilityDisconnectDone has triggered. + WaitUntilDisConnectDone(connection); + + // Destroy ui extension user, this testcase should executed in screen-on. + sptr token = nullptr; + ret = AbilityManagerClient::GetInstance()->GetTopAbility(token); + EXPECT_EQ(ret, ERR_OK); + + int resultCode = 0; + Want resultWant; + ret = AbilityManagerClient::GetInstance()->TerminateAbility(token, resultCode, &resultWant); + EXPECT_EQ(ret, ERR_OK); + + // Wait until ability has terminate + WaitUntilProcessDied(observer); + UnregisterApplicationStateObserver(observer); + HILOG_INFO("finish."); +} + +/** + * @tc.name: ConnectUIExtensionAbility_0200 + * @tc.desc: basic function test. + * @tc.type: FUNC + * @tc.require: issueI5OD2E + */ +HWTEST_F(UIExtensionConnectModuleTest, ConnectUIExtensionAbility_0200, TestSize.Level1) +{ + HILOG_INFO("start."); + + auto currentId = GetSelfTokenID(); + SetNativeToken(); + + auto observer = sptr::MakeSptr(); + RegisterApplicationStateObserver(observer); + + Want providerWant; + AppExecFwk::ElementName providerElement("0", TARGET_BUNDLE_NAME, TARGET_ABILITY_NAME, TARGET_MODULE_NAME); + providerWant.SetElement(providerElement); + + auto connection = sptr::MakeSptr(); + ASSERT_NE(connection, nullptr); + + auto sessionInfo = sptr::MakeSptr(); + ASSERT_NE(sessionInfo, nullptr); + + // Connect ui extension ability firstly. + auto connectInfo = sptr::MakeSptr(); + ASSERT_NE(connectInfo, nullptr); + connectInfo->hostBundleName = USER_BUNDLE_NAME; + connectInfo->uiExtensionAbilityId = 0; + auto ret = AbilityManagerClient::GetInstance()->ConnectUIExtensionAbility(providerWant, connection, sessionInfo, + DEFAULT_INVAL_VALUE, connectInfo); + EXPECT_EQ(ret, ERR_OK); + HILOG_INFO("UIExtensonAbility id %{public}d", connectInfo->uiExtensionAbilityId); + EXPECT_NE(connectInfo->uiExtensionAbilityId, 0); + + // Wait until OnAbilityConnectDone has triggered. + WaitUntilConnectDone(connection); + + // start ui extension user + Want userWant; + AppExecFwk::ElementName userElement("0", USER_BUNDLE_NAME, USER_ABILITY_NAME, USER_MODULE_NAME); + userWant.SetElement(userElement); + ret = AbilityManagerClient::GetInstance()->StartAbility(userWant); + EXPECT_EQ(ret, ERR_OK); + + // Wait until ability has foregrounded + WaitUntilAbilityForeground(observer); + + // Destroy ui extension user. + sptr token = nullptr; + ret = AbilityManagerClient::GetInstance()->GetTopAbility(token); + EXPECT_EQ(ret, ERR_OK); + + int resultCode = 0; + Want resultWant; + ret = AbilityManagerClient::GetInstance()->TerminateAbility(token, resultCode, &resultWant); + EXPECT_EQ(ret, ERR_OK); + + // Wait until ability has background + WaitUntilAbilityBackground(observer); + + // Disconnect ui extension ability. + ret = AbilityManagerClient::GetInstance()->DisconnectAbility(connection); + EXPECT_EQ(ret, ERR_OK); + + // Wait until OnAbilityDisconnectDone has triggered. + WaitUntilDisConnectDone(connection); + + // Wait until ability has terminate + WaitUntilProcessDied(observer); + + SetSelfTokenID(currentId); + UnregisterApplicationStateObserver(observer); + HILOG_INFO("finish."); +} + +/** + * @tc.name: ConnectUIExtensionAbility_0300 + * @tc.desc: basic function test. + * @tc.type: FUNC + * @tc.require: issueI5OD2E + */ +HWTEST_F(UIExtensionConnectModuleTest, ConnectUIExtensionAbility_0300, TestSize.Level1) +{ + HILOG_INFO("start."); + + auto currentId = GetSelfTokenID(); + SetNativeToken(); + + auto observer = sptr::MakeSptr(); + RegisterApplicationStateObserver(observer); + + // start ui extension user + Want userWant; + AppExecFwk::ElementName userElement("0", USER_BUNDLE_NAME, USER_ABILITY_NAME, USER_MODULE_NAME); + userWant.SetElement(userElement); + auto ret = AbilityManagerClient::GetInstance()->StartAbility(userWant); + EXPECT_EQ(ret, ERR_OK); + + // Wait until ability has foregrounded + WaitUntilAbilityForeground(observer); + + // Destroy ui extension user. + sptr token = nullptr; + ret = AbilityManagerClient::GetInstance()->GetTopAbility(token); + EXPECT_EQ(ret, ERR_OK); + + // Minimize ui extension user + ret = AbilityManagerClient::GetInstance()->MinimizeAbility(token); + EXPECT_EQ(ret, ERR_OK); + + // Wait until ability has background + WaitUntilAbilityBackground(observer); + + int resultCode = 0; + Want resultWant; + ret = AbilityManagerClient::GetInstance()->TerminateAbility(token, resultCode, &resultWant); + EXPECT_EQ(ret, ERR_OK); + + // Wait until ability has terminate + WaitUntilProcessDied(observer); + + SetSelfTokenID(currentId); + UnregisterApplicationStateObserver(observer); + HILOG_INFO("finish."); +} + +/** + * @tc.name: ConnectUIExtensionAbility_0400 + * @tc.desc: basic function test. + * @tc.type: FUNC + * @tc.require: issueI5OD2E + */ +HWTEST_F(UIExtensionConnectModuleTest, ConnectUIExtensionAbility_0400, TestSize.Level1) +{ + HILOG_INFO("start."); + + auto currentId = GetSelfTokenID(); + SetNativeToken(); + + auto observer = sptr::MakeSptr(); + RegisterApplicationStateObserver(observer); + + Want providerWant; + AppExecFwk::ElementName providerElement("0", TARGET_BUNDLE_NAME, TARGET_ABILITY_NAME, TARGET_MODULE_NAME); + providerWant.SetElement(providerElement); + + auto connection = sptr::MakeSptr(); + ASSERT_NE(connection, nullptr); + + auto sessionInfo = sptr::MakeSptr(); + ASSERT_NE(sessionInfo, nullptr); + + // Connect ui extension ability firstly. + auto connectInfo = sptr::MakeSptr(); + ASSERT_NE(connectInfo, nullptr); + connectInfo->hostBundleName = USER_BUNDLE_NAME; + connectInfo->uiExtensionAbilityId = 0; + auto ret = AbilityManagerClient::GetInstance()->ConnectUIExtensionAbility(providerWant, connection, sessionInfo, + DEFAULT_INVAL_VALUE, connectInfo); + EXPECT_EQ(ret, ERR_OK); + HILOG_INFO("UIExtensonAbility id %{public}d", connectInfo->uiExtensionAbilityId); + EXPECT_NE(connectInfo->uiExtensionAbilityId, 0); + + // Wait until OnAbilityConnectDone has triggered. + WaitUntilConnectDone(connection); + + // Disconnect ui extension ability. + // wish can't be destroyed, cause there exist ui extension component. + ret = AbilityManagerClient::GetInstance()->DisconnectAbility(connection); + EXPECT_EQ(ret, ERR_OK); + + // Wait until OnAbilityDisconnectDone has triggered. + WaitUntilDisConnectDone(connection); + + // Wait until ability has terminate + WaitUntilProcessDied(observer); + + SetSelfTokenID(currentId); + UnregisterApplicationStateObserver(observer); + HILOG_INFO("finish."); +} + +/** + * @tc.name: ConnectUIExtensionAbility_0500 + * @tc.desc: basic function test. + * @tc.type: FUNC + * @tc.require: issueI5OD2E + */ +HWTEST_F(UIExtensionConnectModuleTest, ConnectUIExtensionAbility_0500, TestSize.Level1) +{ + HILOG_INFO("start."); + + auto currentId = GetSelfTokenID(); + SetNativeToken(); + + auto observer = sptr::MakeSptr(); + RegisterApplicationStateObserver(observer); + + Want providerWant; + AppExecFwk::ElementName providerElement("0", TARGET_BUNDLE_NAME, TARGET_ABILITY_NAME, TARGET_MODULE_NAME); + providerWant.SetElement(providerElement); + + auto connection = sptr::MakeSptr(); + ASSERT_NE(connection, nullptr); + + auto sessionInfo = sptr::MakeSptr(); + ASSERT_NE(sessionInfo, nullptr); + + // Connect ui extension ability firstly. + auto connectInfo = sptr::MakeSptr(); + ASSERT_NE(connectInfo, nullptr); + connectInfo->hostBundleName = USER_BUNDLE_NAME; + connectInfo->uiExtensionAbilityId = 0; + auto ret = AbilityManagerClient::GetInstance()->ConnectUIExtensionAbility(providerWant, connection, sessionInfo, + DEFAULT_INVAL_VALUE, connectInfo); + EXPECT_EQ(ret, ERR_OK); + HILOG_INFO("UIExtensonAbility id %{public}d", connectInfo->uiExtensionAbilityId); + EXPECT_NE(connectInfo->uiExtensionAbilityId, 0); + + // Wait until OnAbilityConnectDone has triggered. + WaitUntilConnectDone(connection); + + // Send uiextensionability id to ui extension user + // start ui extension user + Want userWant; + AppExecFwk::ElementName userElement("0", USER_BUNDLE_NAME, USER_ABILITY_NAME, USER_MODULE_NAME); + userWant.SetElement(userElement); + ret = AbilityManagerClient::GetInstance()->StartAbility(userWant); + EXPECT_EQ(ret, ERR_OK); + + // Wait until ability has foregrounded + WaitUntilAbilityForeground(observer); + + // Disconnect ui extension ability. + // wish can't be destroyed, cause there exist ui extension component. + ret = AbilityManagerClient::GetInstance()->DisconnectAbility(connection); + EXPECT_EQ(ret, ERR_OK); + + // Wait until OnAbilityDisconnectDone has triggered. + WaitUntilDisConnectDone(connection); + + // Destroy ui extension user, this testcase should executed in screen-on. + sptr token = nullptr; + ret = AbilityManagerClient::GetInstance()->GetTopAbility(token); + EXPECT_EQ(ret, ERR_OK); + + // Minimize ui extension user + ret = AbilityManagerClient::GetInstance()->MinimizeAbility(token); + EXPECT_EQ(ret, ERR_OK); + + // Wait until ability has background + WaitUntilAbilityBackground(observer); + + int resultCode = 0; + Want resultWant; + ret = AbilityManagerClient::GetInstance()->TerminateAbility(token, resultCode, &resultWant); + EXPECT_EQ(ret, ERR_OK); + + // Wait until ability has terminate + WaitUntilProcessDied(observer); + + SetSelfTokenID(currentId); + UnregisterApplicationStateObserver(observer); + HILOG_INFO("finish."); +} + +/** + * @tc.name: ConnectUIExtensionAbility_0600 + * @tc.desc: basic function test. + * @tc.type: FUNC + * @tc.require: issueI5OD2E + */ +HWTEST_F(UIExtensionConnectModuleTest, ConnectUIExtensionAbility_0600, TestSize.Level1) +{ + HILOG_INFO("start."); + + auto currentId = GetSelfTokenID(); + SetNativeToken(); + + auto observer = sptr::MakeSptr(); + RegisterApplicationStateObserver(observer); + + Want providerWant; + AppExecFwk::ElementName providerElement("0", TARGET_BUNDLE_NAME, TARGET_ABILITY_NAME, TARGET_MODULE_NAME); + providerWant.SetElement(providerElement); + + auto connection = sptr::MakeSptr(); + ASSERT_NE(connection, nullptr); + + auto sessionInfo = sptr::MakeSptr(); + ASSERT_NE(sessionInfo, nullptr); + + // Connect ui extension ability firstly. + auto connectInfo = sptr::MakeSptr(); + ASSERT_NE(connectInfo, nullptr); + connectInfo->hostBundleName = USER_BUNDLE_NAME; + connectInfo->uiExtensionAbilityId = 0; + auto ret = AbilityManagerClient::GetInstance()->ConnectUIExtensionAbility(providerWant, connection, sessionInfo, + DEFAULT_INVAL_VALUE, connectInfo); + EXPECT_EQ(ret, ERR_OK); + HILOG_INFO("UIExtensonAbility id %{public}d", connectInfo->uiExtensionAbilityId); + EXPECT_NE(connectInfo->uiExtensionAbilityId, 0); + + // Wait until OnAbilityConnectDone has triggered. + WaitUntilConnectDone(connection); + + // start ui extension user + Want userWant; + AppExecFwk::ElementName userElement("0", USER_BUNDLE_NAME, USER_ABILITY_NAME, USER_MODULE_NAME); + userWant.SetElement(userElement); + ret = AbilityManagerClient::GetInstance()->StartAbility(userWant); + EXPECT_EQ(ret, ERR_OK); + + // Wait until ability has foregrounded + WaitUntilAbilityForeground(observer); + + // Destroy ui extension user. + sptr token = nullptr; + ret = AbilityManagerClient::GetInstance()->GetTopAbility(token); + EXPECT_EQ(ret, ERR_OK); + + // Minimize ui extension user + ret = AbilityManagerClient::GetInstance()->MinimizeAbility(token); + EXPECT_EQ(ret, ERR_OK); + + // Wait until ability has background + WaitUntilAbilityBackground(observer); + + int resultCode = 0; + Want resultWant; + ret = AbilityManagerClient::GetInstance()->TerminateAbility(token, resultCode, &resultWant); + EXPECT_EQ(ret, ERR_OK); + + // Wait until ability has background + WaitUntilAbilityBackground(observer); + + // Disconnect ui extension ability. + ret = AbilityManagerClient::GetInstance()->DisconnectAbility(connection); + EXPECT_EQ(ret, ERR_OK); + + // Wait until OnAbilityDisconnectDone has triggered. + WaitUntilDisConnectDone(connection); + + SetSelfTokenID(currentId); + UnregisterApplicationStateObserver(observer); + HILOG_INFO("finish."); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test_connection.cpp b/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test_connection.cpp new file mode 100644 index 00000000000..5695b9e14e5 --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test_connection.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ui_extension_connect_module_test_connection.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { +void UIExtensionConnectModuleTestConnection::OnAbilityConnectDone(const AppExecFwk::ElementName& element, + const sptr& remoteObject, int resultCode) +{ + HILOG_INFO("element: %{public}s", element.GetURI().c_str()); + std::unique_lock lock(connectMutex_); + connectFinished_ = true; + connectCondation_.notify_one(); +} + +void UIExtensionConnectModuleTestConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName& element, + int resultCode) +{ + HILOG_INFO("element: %{public}s", element.GetURI().c_str()); + std::unique_lock lock(connectMutex_); + disConnectFinished_ = true; + connectCondation_.notify_one(); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test_connection.h b/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test_connection.h new file mode 100644 index 00000000000..3894bb1d873 --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test_connection.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_UI_EXTENSION_CONNECT_MODULE_TEST_CONNECTION_H +#define OHOS_ABILITY_RUNTIME_UI_EXTENSION_CONNECT_MODULE_TEST_CONNECTION_H + +#include "ability_connect_callback_stub.h" + +namespace OHOS { +namespace AAFwk { +class UIExtensionConnectModuleTestConnection : public AbilityConnectionStub { +public: + UIExtensionConnectModuleTestConnection() = default; + ~UIExtensionConnectModuleTestConnection() = default; + + std::condition_variable connectCondation_; + std::mutex connectMutex_; + bool connectFinished_ = false; + bool disConnectFinished_ = false; + +private: + void OnAbilityConnectDone(const AppExecFwk::ElementName& element, + const sptr& remoteObject, int resultCode) override; + void OnAbilityDisconnectDone(const AppExecFwk::ElementName& element, int resultCode) override; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_UI_EXTENSION_CONNECT_MODULE_TEST_CONNECTION_H diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test_observer.cpp b/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test_observer.cpp new file mode 100644 index 00000000000..459fdc34078 --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test_observer.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ui_extension_connect_module_test_observer.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { +namespace { +const std::string TARGET_BUNDLE_NAME = "com.ohos.uiextensionprovider"; +} // namespace + +void UIExtensionConnectModuleTestObserver::OnProcessCreated(const AppExecFwk::ProcessData &processData) +{ + HILOG_INFO("bundleName: %{public}s, abilityState: %{public}d", processData.bundleName.c_str(), processData.state); + std::unique_lock lock(observerMutex_); + if (processData.bundleName == TARGET_BUNDLE_NAME) { + processCreated_ = true; + observerCondation_.notify_one(); + } +} + +void UIExtensionConnectModuleTestObserver::OnProcessStateChanged(const AppExecFwk::ProcessData &processData) +{ + HILOG_INFO("bundleName: %{public}s, abilityState: %{public}d", processData.bundleName.c_str(), processData.state); + std::unique_lock lock(observerMutex_); + if (processData.bundleName == TARGET_BUNDLE_NAME) { + if (processData.state == AppExecFwk::AppProcessState::APP_STATE_FOREGROUND) { + processForegrounded_ = true; + observerCondation_.notify_one(); + } else if (processData.state == AppExecFwk::AppProcessState::APP_STATE_BACKGROUND) { + processBackgrounded_ = true; + observerCondation_.notify_one(); + } + } +} + +void UIExtensionConnectModuleTestObserver::OnProcessDied(const AppExecFwk::ProcessData &processData) +{ + HILOG_INFO("bundleName: %{public}s, abilityState: %{public}d", processData.bundleName.c_str(), processData.state); + std::unique_lock lock(observerMutex_); + if (processData.bundleName == TARGET_BUNDLE_NAME) { + processDied_ = true; + observerCondation_.notify_one(); + } +} + +void UIExtensionConnectModuleTestObserver::OnAbilityStateChanged(const AppExecFwk::AbilityStateData &abilityStateData) +{ + HILOG_INFO("bundleName: %{public}s, abilityState: %{public}d", abilityStateData.bundleName.c_str(), + abilityStateData.abilityState); +} + +void UIExtensionConnectModuleTestObserver::OnExtensionStateChanged(const AppExecFwk::AbilityStateData &abilityStateData) +{ + HILOG_INFO("bundleName: %{public}s, abilityState: %{public}d", abilityStateData.bundleName.c_str(), + abilityStateData.abilityState); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test_observer.h b/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test_observer.h new file mode 100644 index 00000000000..c988415ac02 --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_connect_module_test/ui_extension_connect_module_test_observer.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_UI_EXTENSION_CONNECT_MODULE_TEST_OBSERVER_H +#define OHOS_ABILITY_RUNTIME_UI_EXTENSION_CONNECT_MODULE_TEST_OBSERVER_H + +#include "application_state_observer_stub.h" + +namespace OHOS { +namespace AAFwk { +class UIExtensionConnectModuleTestObserver : public AppExecFwk::ApplicationStateObserverStub { +public: + UIExtensionConnectModuleTestObserver() = default; + ~UIExtensionConnectModuleTestObserver() = default; + + std::condition_variable observerCondation_; + std::mutex observerMutex_; + bool processCreated_ = false; + bool processForegrounded_ = false; + bool processBackgrounded_ = false; + bool processDied_ = false; + +private: + void OnProcessCreated(const AppExecFwk::ProcessData &processData) override; + void OnProcessStateChanged(const AppExecFwk::ProcessData &processData) override; + void OnProcessDied(const AppExecFwk::ProcessData &processData) override; + void OnAbilityStateChanged(const AppExecFwk::AbilityStateData &abilityStateData) override; + void OnExtensionStateChanged(const AppExecFwk::AbilityStateData &abilityStateData) override; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_UI_EXTENSION_CONNECT_MODULE_TEST_OBSERVER_H diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/AppScope/app.json b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/AppScope/app.json new file mode 100644 index 00000000000..64896469a1c --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/AppScope/app.json @@ -0,0 +1,12 @@ +{ + "app": { + "bundleName": "com.ohos.uiextensionprovider", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name", + "minAPIVersion": 10, + "targetAPIVersion": 10 + } +} diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/AppScope/resources/base/element/string.json b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/AppScope/resources/base/element/string.json new file mode 100644 index 00000000000..3d475cfa283 --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "UIExtensionProvider" + } + ] +} diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/AppScope/resources/base/media/app_icon.png b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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 void; +export type insertDataToMapCallback = (errCode: number) => void; diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/IdlServiceExt/idl_service_ext_impl.ts b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/IdlServiceExt/idl_service_ext_impl.ts new file mode 100644 index 00000000000..3cf18236468 --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/IdlServiceExt/idl_service_ext_impl.ts @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { processDataCallback } from './i_idl_service_ext'; +import { insertDataToMapCallback } from './i_idl_service_ext'; +import IdlServiceExtStub from './idl_service_ext_stub'; + +const ERR_OK = 0; +const TAG: string = "[IdlServiceExtImpl]"; + +// 开发者需要在这个类型里对接口进行实现 +export default class ServiceExtImpl extends IdlServiceExtStub { + processData(data: number, callback: processDataCallback): void { + // 开发者自行实现业务逻辑 + console.info(TAG, `processData: ${data}`); + callback(ERR_OK, data + 1); + } + + insertDataToMap(key: string, val: number, callback: insertDataToMapCallback): void { + // 开发者自行实现业务逻辑 + console.info(TAG, `insertDataToMap, key: ${key} val: ${val}`); + callback(ERR_OK); + } +} diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/IdlServiceExt/idl_service_ext_proxy.ts b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/IdlServiceExt/idl_service_ext_proxy.ts new file mode 100644 index 00000000000..d6b1cfe4f50 --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/IdlServiceExt/idl_service_ext_proxy.ts @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {processDataCallback} from "./i_idl_service_ext"; +import {insertDataToMapCallback} from "./i_idl_service_ext"; +import IIdlServiceExt from "./i_idl_service_ext"; +import rpc from "@ohos.rpc"; + +export default class IdlServiceExtProxy implements IIdlServiceExt { + constructor(proxy) { + this.proxy = proxy; + } + + processData(data: number, callback: processDataCallback): void + { + let _option = new rpc.MessageOption(); + let _data = new rpc.MessageParcel(); + let _reply = new rpc.MessageParcel(); + _data.writeInt(data); + this.proxy.sendMessageRequest(IdlServiceExtProxy.COMMAND_PROCESS_DATA, _data, _reply, _option).then(function(result) { + if (result.errCode === 0) { + let _errCode = result.reply.readInt(); + if (_errCode != 0) { + let _returnValue = undefined; + callback(_errCode, _returnValue); + return; + } + let _returnValue = result.reply.readInt(); + callback(_errCode, _returnValue); + } else { + console.log("sendMessageRequest failed, errCode: " + result.errCode); + } + }) + } + + insertDataToMap(key: string, val: number, callback: insertDataToMapCallback): void + { + let _option = new rpc.MessageOption(); + let _data = new rpc.MessageParcel(); + let _reply = new rpc.MessageParcel(); + _data.writeString(key); + _data.writeInt(val); + this.proxy.sendMessageRequest(IdlServiceExtProxy.COMMAND_INSERT_DATA_TO_MAP, _data, _reply, _option).then(function(result) { + if (result.errCode === 0) { + let _errCode = result.reply.readInt(); + callback(_errCode); + } else { + console.log("sendMessageRequest failed, errCode: " + result.errCode); + } + }) + } + + static readonly COMMAND_PROCESS_DATA = 1; + static readonly COMMAND_INSERT_DATA_TO_MAP = 2; + private proxy +} diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/IdlServiceExt/idl_service_ext_stub.ts b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/IdlServiceExt/idl_service_ext_stub.ts new file mode 100644 index 00000000000..af481a1697d --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/IdlServiceExt/idl_service_ext_stub.ts @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {processDataCallback} from "./i_idl_service_ext"; +import {insertDataToMapCallback} from "./i_idl_service_ext"; +import IIdlServiceExt from "./i_idl_service_ext"; +import rpc from "@ohos.rpc"; + +export default class IdlServiceExtStub extends rpc.RemoteObject implements IIdlServiceExt { + constructor(des: string) { + super(des); + } + + async onRemoteMessageRequest(code: number, data, reply, option): Promise { + console.log("onRemoteMessageRequest called, code = " + code); + switch(code) { + case IdlServiceExtStub.COMMAND_PROCESS_DATA: { + let _data = data.readInt(); + this.processData(_data, (errCode, returnValue) => { + reply.writeInt(errCode); + if (errCode == 0) { + reply.writeInt(returnValue); + } + }); + return true; + } + case IdlServiceExtStub.COMMAND_INSERT_DATA_TO_MAP: { + let _key = data.readString(); + let _val = data.readInt(); + this.insertDataToMap(_key, _val, (errCode) => { + reply.writeInt(errCode); + }); + return true; + } + default: { + console.log("invalid request code" + code); + break; + } + } + return false; + } + + processData(data: number, callback: processDataCallback): void{} + insertDataToMap(key: string, val: number, callback: insertDataToMapCallback): void{} + + static readonly COMMAND_PROCESS_DATA = 1; + static readonly COMMAND_INSERT_DATA_TO_MAP = 2; +} diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/entryability/EntryAbility.ets b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 00000000000..078a52eb8bb --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import hilog from '@ohos.hilog'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import Want from '@ohos.app.ability.Want'; +import window from '@ohos.window'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage) { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground() { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground() { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/pages/Extension.ets b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/pages/Extension.ets new file mode 100644 index 00000000000..4b2ee4d0244 --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/pages/Extension.ets @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'; + +let storage = LocalStorage.getShared(); +const TAG: string = '[testTag] ExtensionPage' + +@Entry(storage) +@Component +struct Extension { + @State message: string = 'UIExtension Provider'; + private session: UIExtensionContentSession | undefined = storage.get('session'); + + onPageShow() { + console.info(TAG, 'show'); + // if u wanna use setReceiveDataCallback, you should be a system app. + // this.session?.setReceiveDataCallback((data) => { + // this.message = JSON.stringify(data); + // }) + } + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(20) + .fontWeight(FontWeight.Bold) + .textAlign(TextAlign.Center) + + Button("send data") + .width('80%') + .type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .onClick(() => { + this.session?.sendData({ "data": 543321 }); + }) + + Button("terminate self") + .width('80%') + .type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .onClick(() => { + this.session?.terminateSelf(); + storage.clear(); + }) + + Button("terminate self with result") + .width('80%') + .type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .onClick(() => { + this.session?.terminateSelfWithResult({ + resultCode: 0, + want: { + bundleName: "com.ohos.uiextensionprovider", + parameters: { "result": 123456 } + } + }) + }) + } + } + .height('100%') + } +} \ No newline at end of file diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/pages/Index.ets b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/pages/Index.ets new file mode 100644 index 00000000000..c0e40e0d3a9 --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@Entry +@Component +struct Index { + @State message: string = 'UIExtension MainPage'; + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(30) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/uiextensionability/UIExtensionAbility.ets b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/uiextensionability/UIExtensionAbility.ets new file mode 100644 index 00000000000..3a8a1405ca3 --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/ets/uiextensionability/UIExtensionAbility.ets @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import UIExtensionAbility from '@ohos.app.ability.UIExtensionAbility' +import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'; +import Want from '@ohos.app.ability.Want'; +import ServiceExtImpl from '../IdlServiceExt/idl_service_ext_impl'; + +const TAG: string = '[testTag] UIExtAbility'; + +export default class UIExtAbility extends UIExtensionAbility { + serviceExtImpl = new ServiceExtImpl("ExtImpl"); + onCreate() { + console.log(TAG, `onCreate`); + } + + onForeground() { + console.log(TAG, `onForeground`); + } + + onBackground() { + console.log(TAG, `onBackground`); + } + + onDestroy() { + console.log(TAG, `onDestroy`); + } + + onSessionCreate(want: Want, session: UIExtensionContentSession) { + console.log(TAG, `onSessionCreate, want: ${JSON.stringify(want)}`); + let storage: LocalStorage = new LocalStorage(); + storage.setOrCreate('session', session); + session.loadContent('pages/Extension', storage); + } + + onSessionDestroy(session: UIExtensionContentSession) { + console.log(TAG, `onSessionDestroy`); + } + + // just for test connect ui extension ability + onConnect(want: Want) { + console.log(TAG, `onConnect, want: ${JSON.stringify(want)}`); + return this.serviceExtImpl; + } + + onDisConnect(want: Want) { + console.log(TAG, `onDisConnect, want: ${JSON.stringify(want)}`); + } +}; \ No newline at end of file diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/module.json b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/module.json new file mode 100644 index 00000000000..2adb8dedbaf --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/module.json @@ -0,0 +1,48 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:icon", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "UIExtensionProvider", + "srcEntry": "./ets/uiextensionability/UIExtensionAbility.ets", + "description": "$string:UIExtensionAbility_desc", + "label": "$string:UIExtensionAbility_label", + "type": "sys/commonUI", + "exported": true + } + ] + } +} \ No newline at end of file diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/resources/base/element/color.json b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/resources/base/element/color.json new file mode 100644 index 00000000000..3c712962da3 --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/resources/base/element/string.json b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/resources/base/element/string.json new file mode 100644 index 00000000000..8c40e6e7a04 --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/resources/base/element/string.json @@ -0,0 +1,24 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + }, + { + "name": "UIExtensionAbility_desc", + "value": "description" + }, + { + "name": "UIExtensionAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/resources/base/media/icon.png b/test/moduletest/ui_extension_ability_test/ui_extension_provider_bundle/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 zcmX|G1ymHk)?T_}Vd;>R?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}yR?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}yH>C#NWzM$Lc43bU^DQelNt0w zyWhFr-92}|^PM{vBzag`#_VQI^S3-!I=d~&Gk_#d$7Zo09>`3~SkkOv;T$fT1(K

=ht@`Xj92=M1Tg6*V(hJ|zZSRf#9ctYWz#})}Q z6TBJ!^ z^B&CSad^UUe(6#^L52l3+(`!M=R#tcNGcHv#nL(bIOYuFK^m4wWulT|8eTSsKgb}6 z`*19T(+{&n2!{_BcnBxSJkNngaUU7LgMxlWl>wa4U_n1g#Od5&Yq8_Ou*d1KV_{}V z0_KM()mmM?Txl?BRa!Z0RQ98F1gh1_RSLNrwnkhqrA1(uR;#j9xlH~Bkp$DRvN�RE?o@*lSVm^QC729YpE>@+k|2< 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 { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground() { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground() { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/ets/pages/Index.ets b/test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/ets/pages/Index.ets new file mode 100644 index 00000000000..09e0cdc96da --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@Entry +@Component +struct Index { + @State message: string = 'UIExtension User'; + private myProxy: UIExtensionProxy | undefined = undefined; + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(30) + .size({ width: '100%', height: '50' }) + .fontWeight(FontWeight.Bold) + .textAlign(TextAlign.Center) + + UIExtensionComponent( + { + bundleName: 'com.ohos.uiextensionprovider', + abilityName: 'UIExtensionProvider', + moduleName: 'entry', + parameters: { + 'ability.want.params.uiExtensionType': 'sys/commonUI', + } + }) + .onRemoteReady((proxy) => { + this.myProxy = proxy; + }) + .onReceive((data) => { + this.message = JSON.stringify(data); + }) + .onResult((data) => { + this.message = JSON.stringify(data); + }) + .onRelease((code) => { + this.message = "release code: " + code; + }) + .offset({ x: 0, y: 30 }) + .size({ width: 300, height: 300 }) + .border({ width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Dotted }) + + Button("sendData") + .type(ButtonType.Capsule) + .offset({ x: 0, y: 60 }) + .width('80%') + .type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .onClick(() => { + this.myProxy?.send({ + "data": 123456, + "message": "data from component" + }) + }) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/module.json b/test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/module.json new file mode 100644 index 00000000000..6c07d9d8839 --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/module.json @@ -0,0 +1,38 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:icon", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ] + } +} \ No newline at end of file diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/resources/base/element/color.json b/test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/resources/base/element/color.json new file mode 100644 index 00000000000..3c712962da3 --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/resources/base/element/string.json b/test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/resources/base/element/string.json new file mode 100644 index 00000000000..f94595515a9 --- /dev/null +++ b/test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/resources/base/media/icon.png b/test/moduletest/ui_extension_ability_test/ui_extension_user_bundle/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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 SsB6J1<4XE-e6x8gH~bfG#!+$r literal 0 HcmV?d00001 -- Gitee