From 82ee4aaed6504ec4f32bd0a9e1962d7d6ea2f44d Mon Sep 17 00:00:00 2001 From: guxiang Date: Sat, 21 Jun 2025 00:14:07 +0800 Subject: [PATCH] All-scenario PC/Pad collaboration Signed-off-by: guxiang --- .../ans/src/notification_operation_info.cpp | 18 ++ frameworks/ans/test/unittest/BUILD.gn | 1 + .../notification_operation_info_test.cpp | 88 +++++++++ .../ans_notification_unit_test.cpp | 124 ++++++++++++ frameworks/js/napi/include/subscribe.h | 3 +- frameworks/js/napi/src/subscribe.cpp | 36 +++- .../js/napi/src/subscribe/napi_subscribe.cpp | 12 +- interfaces/inner_api/notification_constant.h | 7 + .../inner_api/notification_operation_info.h | 8 +- ...tification_distributed_manager_service.cpp | 3 +- ...ation_distributed_manager_service_test.cpp | 15 ++ services/distributed/BUILD.gn | 1 + ...liveview_all_scenarios_extension_wrapper.h | 8 + .../soft_bus/distributed_operation_service.h | 5 + .../soft_bus/distributed_publish_service.h | 3 +- ...distributed_unlock_listener_oper_service.h | 91 +++++++++ .../distributed/include/tlv_box/request_box.h | 7 +- .../include/tlv_box/response_box.h | 4 + .../distributed/include/tlv_box/tlv_box.h | 4 + ...veview_all_scenarios_extension_wrapper.cpp | 35 ++++ .../soft_bus/distributed_observer_service.cpp | 6 + .../distributed_operation_service.cpp | 142 +++++++++++++- .../distributed_publish_service_v2.cpp | 79 +++++++- ...stributed_unlock_listener_oper_service.cpp | 177 ++++++++++++++++++ .../distributed/src/tlv_box/request_box.cpp | 77 ++++++++ .../distributed/src/tlv_box/response_box.cpp | 32 ++++ 26 files changed, 960 insertions(+), 26 deletions(-) create mode 100644 frameworks/ans/test/unittest/notification_operation_info_test.cpp create mode 100644 services/distributed/include/soft_bus/distributed_unlock_listener_oper_service.h create mode 100644 services/distributed/src/soft_bus/distributed_unlock_listener_oper_service.cpp diff --git a/frameworks/ans/src/notification_operation_info.cpp b/frameworks/ans/src/notification_operation_info.cpp index 692e01622..2dd14c208 100644 --- a/frameworks/ans/src/notification_operation_info.cpp +++ b/frameworks/ans/src/notification_operation_info.cpp @@ -75,6 +75,16 @@ void NotificationOperationInfo::SetOperationType(const OperationType& operationT operationType_ = operationType; } +int32_t NotificationOperationInfo::GetBtnIndex() const +{ + return btnIndex_; +} + +void NotificationOperationInfo::SetBtnIndex(const int32_t& btnIndex) +{ + btnIndex_ = btnIndex; +} + std::string NotificationOperationInfo::Dump() { return "NotificationOperationInfo{ " @@ -82,6 +92,7 @@ std::string NotificationOperationInfo::Dump() ", eventId = " + eventId_ + ", actionName = " + actionName_ + ", operationType = " + std::to_string(static_cast(operationType_)) + + ", btnIndex = " + std::to_string(btnIndex_) + " }"; } @@ -112,6 +123,11 @@ bool NotificationOperationInfo::Marshalling(Parcel &parcel) const return false; } + if (!parcel.WriteInt32(static_cast(btnIndex_))) { + ANS_LOGE("Failed to write operationType"); + return false; + } + return true; } @@ -139,6 +155,8 @@ bool NotificationOperationInfo::ReadFromParcel(Parcel &parcel) operationType_ = static_cast(parcel.ReadInt32()); + btnIndex_ = static_cast(parcel.ReadInt32()); + return true; } diff --git a/frameworks/ans/test/unittest/BUILD.gn b/frameworks/ans/test/unittest/BUILD.gn index 0db5c73f7..66a60a2a1 100644 --- a/frameworks/ans/test/unittest/BUILD.gn +++ b/frameworks/ans/test/unittest/BUILD.gn @@ -67,6 +67,7 @@ ohos_unittest("ans_test") { "${frameworks_module_ans_path}/test/unittest/notification_unified_group_info_test.cpp", "${frameworks_module_ans_path}/test/unittest/notification_user_input_test.cpp", "${frameworks_module_ans_path}/test/unittest/push_promise_callback_test.cpp", + "${frameworks_module_ans_path}/test/unittest/notification_operation_info_test.cpp", ] cflags = [ diff --git a/frameworks/ans/test/unittest/notification_operation_info_test.cpp b/frameworks/ans/test/unittest/notification_operation_info_test.cpp new file mode 100644 index 000000000..76e3d86c9 --- /dev/null +++ b/frameworks/ans/test/unittest/notification_operation_info_test.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define private public +#define protected public +#include "notification_operation_info.h" +#undef private +#undef protected + +using namespace testing::ext; +namespace OHOS { +namespace Notification { +class NotificationOperationInfoTest : public testing::Test { +public: + static void SetUpTestCase() {} + static void TearDownTestCase() {} + void SetUp() {} + void TearDown() {} +}; + +/** + * @tc.name: SetBtnIndex_0100 + * @tc.desc: Test SetBtnIndex. + * @tc.type: FUNC + * @tc.require: issueI5WBBH + */ +HWTEST_F(NotificationOperationInfoTest, SetBtnIndex_0100, Function | SmallTest | Level1) +{ + NotificationOperationInfo notificationOperationInfo; + notificationOperationInfo.SetBtnIndex(2); + EXPECT_EQ(notificationOperationInfo.GetBtnIndex(), 2); +} + +/** + * @tc.name: Dump_0100 + * @tc.desc: Test Dump. + * @tc.type: FUNC + * @tc.require: issueI5WBBH + */ +HWTEST_F(NotificationOperationInfoTest, Dump_0100, Function | SmallTest | Level1) +{ + NotificationOperationInfo notificationOperationInfo; + std::string expString = "NotificationOperationInfo{ hashCode = hashCode, eventId = 1, actionName = actionName, " \ + "operationType = 0, btnIndex = 2 }"; + notificationOperationInfo.SetHashCode("hashCode"); + notificationOperationInfo.SetEventId("1"); + notificationOperationInfo.SetActionName("actionName"); + notificationOperationInfo.SetOperationType(OperationType::DISTRIBUTE_OPERATION_JUMP); + notificationOperationInfo.SetBtnIndex(2); + EXPECT_EQ(notificationOperationInfo.Dump(), expString); +} + +/** + * @tc.name: Marshalling_0100 + * @tc.desc: Test Marshalling. + * @tc.type: FUNC + * @tc.require: issueI5WBBH + */ +HWTEST_F(NotificationOperationInfoTest, Marshalling_0100, Function | SmallTest | Level1) +{ + Parcel parcel; + NotificationOperationInfo notificationOperationInfo; + notificationOperationInfo.SetHashCode("hashCode"); + notificationOperationInfo.SetEventId("1"); + notificationOperationInfo.SetActionName("actionName"); + notificationOperationInfo.SetOperationType(OperationType::DISTRIBUTE_OPERATION_JUMP); + notificationOperationInfo.SetBtnIndex(2); + EXPECT_TRUE(notificationOperationInfo.Marshalling(parcel)); + NotificationOperationInfo ntfOperInfoRes; + EXPECT_TRUE(ntfOperInfoRes.ReadFromParcel(parcel)); + EXPECT_EQ(ntfOperInfoRes.GetBtnIndex(), 2); +} +} +} \ No newline at end of file diff --git a/frameworks/core/test/unittest/ans_notification_test/ans_notification_unit_test.cpp b/frameworks/core/test/unittest/ans_notification_test/ans_notification_unit_test.cpp index 17bed8023..e0e86f6cb 100644 --- a/frameworks/core/test/unittest/ans_notification_test/ans_notification_unit_test.cpp +++ b/frameworks/core/test/unittest/ans_notification_test/ans_notification_unit_test.cpp @@ -1166,6 +1166,31 @@ HWTEST_F(AnsNotificationUnitTest, SubscribeNotificationSelf_0100, Function | Med EXPECT_EQ(ret, ERR_ANS_SERVICE_NOT_CONNECTED); } +/* + * @tc.name: SubscribeNotificationSelf_0400 + * @tc.desc: test SubscribeNotificationSelf with nullptr param. + * @tc.type: FUNC + * @tc.require: #I62SME + */ +HWTEST_F(AnsNotificationUnitTest, SubscribeNotificationSelf_0400, Function | MediumTest | Level1) +{ + ErrCode ret = ans_->SubscribeNotificationSelf(nullptr); + EXPECT_EQ(ret, ERR_ANS_INVALID_PARAM); +} + +/* + * @tc.name: SubscribeNotificationSelf_0500 + * @tc.desc: test SubscribeNotificationSelf ErrCode ERR_ANS_SERVICE_NOT_CONNECTED. + * @tc.type: FUNC + * @tc.require: #I62SME + */ +HWTEST_F(AnsNotificationUnitTest, SubscribeNotificationSelf_0500, Function | MediumTest | Level1) +{ + std::shared_ptr subscriberPtr = std::make_shared(); + ErrCode ret = ans_->SubscribeNotificationSelf(subscriberPtr); + EXPECT_EQ(ret, ERR_ANS_SERVICE_NOT_CONNECTED); +} + /* * @tc.name: SubscribeLocalLiveViewNotification_0100 * @tc.desc: test SubscribeLocalLiveViewNotification ErrCode ERR_ANS_SERVICE_NOT_CONNECTED. @@ -1308,6 +1333,18 @@ HWTEST_F(AnsNotificationUnitTest, UnSubscribeNotification_0400, Function | Mediu EXPECT_EQ(ret1, ERR_ANS_SERVICE_NOT_CONNECTED); } +/* + * @tc.name: UnSubscribeNotification_0700 + * @tc.desc: test UnSubscribeNotification when subscriber is nullptr. + * @tc.type: FUNC + * @tc.require: #I62SME + */ +HWTEST_F(AnsNotificationUnitTest, UnSubscribeNotification_0700, Function | MediumTest | Level1) +{ + ErrCode ret = ans_->UnSubscribeNotification(nullptr, nullptr); + EXPECT_EQ(ret, ERR_ANS_INVALID_PARAM); +} + /* * @tc.name: SetNotificationsEnabledForSpecifiedBundle_0100 * @tc.desc: test SetNotificationsEnabledForSpecifiedBundle ErrCode ERR_ANS_INVALID_PARAM. @@ -2196,5 +2233,92 @@ HWTEST_F(AnsNotificationUnitTest, SubscribeNotification_0700, Function | MediumT ErrCode ret = ans_->SubscribeNotification(subscriber, info); EXPECT_EQ(ret, ERR_OK); } + +/* + * @tc.name: UnSubscribeNotification_0500 + * @tc.desc: test UnSubscribeNotification normal. + * @tc.type: FUNC + * @tc.require: #I62SME + */ +HWTEST_F(AnsNotificationUnitTest, UnSubscribeNotification_0500, Function | MediumTest | Level1) +{ + auto subscriber = TestAnsSubscriber(); + subscriber.impl_ = nullptr; + ErrCode ret = ans_->UnSubscribeNotification(subscriber); + EXPECT_EQ(ret, ERR_ANS_INVALID_PARAM); +} + +/* + * @tc.name: UnSubscribeNotification_0600 + * @tc.desc: test UnSubscribeNotification normal. + * @tc.type: FUNC + * @tc.require: #I62SME + */ +HWTEST_F(AnsNotificationUnitTest, UnSubscribeNotification_0600, Function | MediumTest | Level1) +{ + auto subscriber = TestAnsSubscriber(); + subscriber.impl_ = nullptr; + auto info = NotificationSubscribeInfo(); + ErrCode ret = ans_->UnSubscribeNotification(subscriber, info); + EXPECT_EQ(ret, ERR_ANS_INVALID_PARAM); +} + +/* + * @tc.name: SubscribeNotificationSelf_0600 + * @tc.desc: test SubscribeNotificationSelf normal. + * @tc.type: FUNC + * @tc.require: #I62SME + */ +HWTEST_F(AnsNotificationUnitTest, SubscribeNotificationSelf_0600, Function | MediumTest | Level1) +{ + std::shared_ptr subscriberPtr = std::make_shared(); + ErrCode ret = ans_->SubscribeNotificationSelf(subscriberPtr); + EXPECT_EQ(ret, ERR_OK); +} + +/* + * @tc.name: SubscribeNotification_0800 + * @tc.desc: test SubscribeNotification normal. + * @tc.type: FUNC + * @tc.require: #I62SME + */ +HWTEST_F(AnsNotificationUnitTest, SubscribeNotification_0800, Function | MediumTest | Level1) +{ + std::shared_ptr subscriberPtr = std::make_shared(); + sptr infoPtr = new (std::nothrow) NotificationSubscribeInfo(); + infoPtr->AddDeviceType("phone"); + ErrCode ret1 = ans_->SubscribeNotification(subscriberPtr, infoPtr); + EXPECT_EQ(ret1, ERR_OK); + ErrCode ret2 = ans_->UnSubscribeNotification(subscriberPtr, infoPtr); + EXPECT_EQ(ret2, ERR_OK); +} + +/* + * @tc.name: SubscribeNotification_0900 + * @tc.desc: test SubscribeNotification when subscribeInfo is nullptr. + * @tc.type: FUNC + * @tc.require: #I62SME + */ +HWTEST_F(AnsNotificationUnitTest, SubscribeNotification_0900, Function | MediumTest | Level1) +{ + std::shared_ptr subscriberPtr = std::make_shared(); + ErrCode ret1 = ans_->SubscribeNotification(subscriberPtr, nullptr); + EXPECT_EQ(ret1, ERR_OK); + ErrCode ret2 = ans_->UnSubscribeNotification(subscriberPtr, nullptr); + EXPECT_EQ(ret2, ERR_OK); +} + +/* + * @tc.name: UnSubscribeNotification_0800 + * @tc.desc: test UnSubscribeNotification when subscriber not in list. + * @tc.type: FUNC + * @tc.require: #I62SME + */ +HWTEST_F(AnsNotificationUnitTest, UnSubscribeNotification_0800, Function | MediumTest | Level1) +{ + std::shared_ptr subscriberPtr = std::make_shared(); + ErrCode ret = ans_->UnSubscribeNotification(subscriberPtr, nullptr); + EXPECT_EQ(ret, ERR_ANS_INVALID_PARAM); +} } // namespace Notification } // namespace OHOS diff --git a/frameworks/js/napi/include/subscribe.h b/frameworks/js/napi/include/subscribe.h index 2e9c0c831..0934a80a7 100644 --- a/frameworks/js/napi/include/subscribe.h +++ b/frameworks/js/napi/include/subscribe.h @@ -211,9 +211,10 @@ struct AsyncCallbackInfoSubscribe { }; struct OperationInfo { - bool withOperationInfo = false; + int32_t operationType; std::string actionName; std::string userInput; + int32_t btnIndex; }; struct AsyncOperationCallbackInfo { diff --git a/frameworks/js/napi/src/subscribe.cpp b/frameworks/js/napi/src/subscribe.cpp index 0c822a57b..4ccd0c84d 100644 --- a/frameworks/js/napi/src/subscribe.cpp +++ b/frameworks/js/napi/src/subscribe.cpp @@ -1707,9 +1707,40 @@ void DelDeletingSubscriber(std::shared_ptr subscriber) } } +napi_value GetParamOperationInfoSub(const napi_env &env, const napi_value &content, OperationInfo& operationInfo) +{ + napi_valuetype valuetype = napi_undefined; + napi_value result = nullptr; + bool hasProperty = false; + NAPI_CALL(env, napi_has_named_property(env, content, "operationType", &hasProperty)); + if (hasProperty) { + napi_get_named_property(env, content, "operationType", &result); + NAPI_CALL(env, napi_typeof(env, result, &valuetype)); + if (valuetype != napi_number) { + return nullptr; + } + int32_t code; + NAPI_CALL(env, napi_get_value_int32(env, result, &code)); + operationInfo.operationType = code; + } + + NAPI_CALL(env, napi_has_named_property(env, content, "buttonIndex", &hasProperty)); + if (hasProperty) { + napi_get_named_property(env, content, "buttonIndex", &result); + NAPI_CALL(env, napi_typeof(env, result, &valuetype)); + if (valuetype != napi_number) { + return nullptr; + } + + int32_t code; + NAPI_CALL(env, napi_get_value_int32(env, result, &code)); + operationInfo.btnIndex = code; + } + return Common::NapiGetNull(env); +} + napi_value GetParamOperationInfo(const napi_env &env, const napi_value &content, OperationInfo& operationInfo) { - operationInfo.withOperationInfo = true; napi_valuetype valuetype = napi_undefined; NAPI_CALL(env, napi_typeof(env, content, &valuetype)); if (valuetype != napi_object) { @@ -1751,7 +1782,8 @@ napi_value GetParamOperationInfo(const napi_env &env, const napi_value &content, NAPI_CALL(env, napi_get_value_string_utf8(env, result, str, LONG_STR_MAX_SIZE - 1, &strLen)); operationInfo.userInput = str; } - return Common::NapiGetNull(env); + + return GetParamOperationInfoSub(env, content, operationInfo); } napi_value ParseParameters(const napi_env &env, const napi_callback_info &info, std::string &hashCode, diff --git a/frameworks/js/napi/src/subscribe/napi_subscribe.cpp b/frameworks/js/napi/src/subscribe/napi_subscribe.cpp index 15eaa9009..ebc781819 100644 --- a/frameworks/js/napi/src/subscribe/napi_subscribe.cpp +++ b/frameworks/js/napi/src/subscribe/napi_subscribe.cpp @@ -45,15 +45,21 @@ void NapiDistributeOperationExecuteCallback(napi_env env, void *data) return; } operationInfo->SetHashCode(asyncCallbackInfo->hashCode); - if (asyncCallbackInfo->operationInfo.withOperationInfo) { + if (asyncCallbackInfo->operationInfo.operationType == + static_cast(OperationType::DISTRIBUTE_OPERATION_REPLY)) { operationInfo->SetOperationType(OperationType::DISTRIBUTE_OPERATION_REPLY); + operationInfo->SetBtnIndex(asyncCallbackInfo->operationInfo.btnIndex); operationInfo->SetActionName(asyncCallbackInfo->operationInfo.actionName); operationInfo->SetUserInput(asyncCallbackInfo->operationInfo.userInput); + } else if (asyncCallbackInfo->operationInfo.operationType < OperationType::DISTRIBUTE_OPERATION_FOR_LIVE_VIEW) { + operationInfo->SetOperationType(OperationType::DISTRIBUTE_OPERATION_REPLY); } else { - operationInfo->SetOperationType(OperationType::DISTRIBUTE_OPERATION_JUMP); + operationInfo->SetOperationType(static_cast(asyncCallbackInfo->operationInfo.operationType)); } int32_t result = NotificationHelper::DistributeOperation(operationInfo, callback); - if (result != ERR_OK || !asyncCallbackInfo->operationInfo.withOperationInfo) { + if (result != ERR_OK || + asyncCallbackInfo->operationInfo.operationType == + static_cast(OperationType::DISTRIBUTE_OPERATION_JUMP)) { callback->OnOperationCallback(result); } } diff --git a/interfaces/inner_api/notification_constant.h b/interfaces/inner_api/notification_constant.h index b1c478578..f72f4374f 100644 --- a/interfaces/inner_api/notification_constant.h +++ b/interfaces/inner_api/notification_constant.h @@ -341,6 +341,11 @@ public: */ static const int32_t USER_LOGOUT_REASON_DELETE = 33; + /** + * Indicates that a notification is deleted because collaboration click. + */ + static const int32_t DISTRIBUTED_COLLABORATIVE_CLICK_DELETE = 34; + /** * Indicates that a notification is deleted for other reasons. */ @@ -380,6 +385,8 @@ public: static constexpr int32_t ANS_UID = 5523; + static constexpr int32_t MAX_BTN_NUM = 3; + // live view max size is 512KB(extra size) + 8KB(base size) = 520KB static constexpr uint64_t NOTIFICATION_MAX_LIVE_VIEW_SIZE = 520ULL * 1024ULL; diff --git a/interfaces/inner_api/notification_operation_info.h b/interfaces/inner_api/notification_operation_info.h index bfebd3895..660e70237 100644 --- a/interfaces/inner_api/notification_operation_info.h +++ b/interfaces/inner_api/notification_operation_info.h @@ -25,7 +25,8 @@ namespace Notification { enum OperationType { DISTRIBUTE_OPERATION_JUMP = 0, - DISTRIBUTE_OPERATION_REPLY + DISTRIBUTE_OPERATION_REPLY, + DISTRIBUTE_OPERATION_FOR_LIVE_VIEW = 32 }; class NotificationOperationInfo : public Parcelable { @@ -64,6 +65,10 @@ public: void SetOperationType(const OperationType& operationType); + int32_t GetBtnIndex() const; + + void SetBtnIndex(const int32_t& btnIndex); + std::string Dump(); /** @@ -90,6 +95,7 @@ private: std::string userInput_; std::string hashCode_; std::string eventId_; + int32_t btnIndex_; OperationType operationType_; }; } // namespace Notification diff --git a/services/ans/src/distributed_manager/advanced_notification_distributed_manager_service.cpp b/services/ans/src/distributed_manager/advanced_notification_distributed_manager_service.cpp index dac1a91b8..a81cb98b8 100644 --- a/services/ans/src/distributed_manager/advanced_notification_distributed_manager_service.cpp +++ b/services/ans/src/distributed_manager/advanced_notification_distributed_manager_service.cpp @@ -326,7 +326,8 @@ ErrCode DistributeOperationParamCheck(const sptr& ope OperationType operationType = operationInfo->GetOperationType(); if (operationType != OperationType::DISTRIBUTE_OPERATION_JUMP && - operationType != OperationType::DISTRIBUTE_OPERATION_REPLY) { + operationType != OperationType::DISTRIBUTE_OPERATION_REPLY && + operationType < OperationType::DISTRIBUTE_OPERATION_FOR_LIVE_VIEW) { ANS_LOGE("operation type is error."); return ERR_ANS_INVALID_PARAM; } diff --git a/services/ans/test/unittest/advanced_notification_service_test/advanced_notification_distributed_manager_service_test.cpp b/services/ans/test/unittest/advanced_notification_service_test/advanced_notification_distributed_manager_service_test.cpp index ab5c44d60..93d96699e 100644 --- a/services/ans/test/unittest/advanced_notification_service_test/advanced_notification_distributed_manager_service_test.cpp +++ b/services/ans/test/unittest/advanced_notification_service_test/advanced_notification_distributed_manager_service_test.cpp @@ -178,6 +178,21 @@ HWTEST_F(AdvancedNotificationDistMgrServiceTest, DistributeOperationParamCheck_1 ASSERT_EQ(ret, (int)ERR_ANS_NON_SYSTEM_APP); } +/** + * @tc.name: DistributeOperationParamCheck_200 + * @tc.desc: Test DistributeOperationParamCheck when invalid operationType. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(AdvancedNotificationDistMgrServiceTest, DistributeOperationParamCheck_200, Function | SmallTest | Level1) +{ + sptr operationInfo = new (std::nothrow) NotificationOperationInfo(); + operationInfo->SetOperationType(static_cast(2)); + sptr callback = nullptr; + auto ret = advancedNotificationService_->DistributeOperation(operationInfo, callback); + ASSERT_EQ(ret, (int)ERR_ANS_INVALID_PARAM); +} + /** * @tc.name: DistributeOperation_100 * @tc.desc: Test DistributeOperation when notificationSvrQueue_ is nullptr. diff --git a/services/distributed/BUILD.gn b/services/distributed/BUILD.gn index 87ab3b7c8..02a7f0235 100644 --- a/services/distributed/BUILD.gn +++ b/services/distributed/BUILD.gn @@ -117,6 +117,7 @@ ohos_shared_library("libdans") { "src/soft_bus/distributed_service.cpp", "src/soft_bus/distributed_subscribe_service_v2.cpp", "src/soft_bus/distributed_subscriber.cpp", + "src/soft_bus/distributed_unlock_listener_oper_service.cpp", "src/tlv_box/batch_remove_box.cpp", "src/tlv_box/box_base.cpp", "src/tlv_box/bundle_icon_box.cpp", diff --git a/services/distributed/include/base/distributed_liveview_all_scenarios_extension_wrapper.h b/services/distributed/include/base/distributed_liveview_all_scenarios_extension_wrapper.h index dc45e89d2..2e94610ef 100644 --- a/services/distributed/include/base/distributed_liveview_all_scenarios_extension_wrapper.h +++ b/services/distributed/include/base/distributed_liveview_all_scenarios_extension_wrapper.h @@ -37,11 +37,17 @@ public: int32_t actionType, const AAFwk::WantParams extraInfo); typedef ErrCode (*SUBSCRIBE_ALL_CONNECT)(); typedef ErrCode (*UNSUBSCRIBE_ALL_CONNECT)(); + typedef ErrCode (*LIVE_VIEW_MULTI_SCREEN_SYNC_OPER)( + sptr &request, const int32_t operationType, const int32_t btnIndex); + typedef ErrCode (*RESTORE_COLLABORATION_WINDOW)(const std::string &networkId); ErrCode UpdateLiveviewDecodeContent(const sptr &request, std::vector &buffer); ErrCode TriggerPushWantAgent(const sptr &request, int32_t actionType, const AAFwk::WantParams extraInfo); ErrCode SubscribeAllConnect(); ErrCode UnSubscribeAllConnect(); + ErrCode LiveViewMultiScreenSyncOper( + sptr &request, const int32_t operationType, const int32_t btnIndex); + int32_t RestoreCollaborationWindow(const std::string &networkId); private: void* ExtensionHandle_ = nullptr; SUBSCRIBE_ALL_CONNECT subscribeHandler_ = nullptr; @@ -49,6 +55,8 @@ private: TRIGGER_PUSH_WANT_AGENT triggerHandler_ = nullptr; UPDATE_LIVEVIEW_ENCODE_CONTENT updateLiveviewEncodeContent_ = nullptr; UPDATE_LIVEVIEW_DECODE_CONTENT updateLiveviewDecodeContent_ = nullptr; + LIVE_VIEW_MULTI_SCREEN_SYNC_OPER liveViewMultiScreenSyncOper_ = nullptr; + RESTORE_COLLABORATION_WINDOW restoreCollaborationWindow_ = nullptr; }; #define DISTRIBUTED_LIVEVIEW_ALL_SCENARIOS_EXTENTION_WRAPPER \ diff --git a/services/distributed/include/soft_bus/distributed_operation_service.h b/services/distributed/include/soft_bus/distributed_operation_service.h index f8861e643..ace513b30 100644 --- a/services/distributed/include/soft_bus/distributed_operation_service.h +++ b/services/distributed/include/soft_bus/distributed_operation_service.h @@ -35,10 +35,15 @@ public: OperationType operationType, uint32_t result); int32_t TriggerReplyApplication(const std::string& hashCode, const NotificationResponseBox& responseBox); void TriggerJumpApplication(const std::string& hashCode); + void DealNonMultiScreenSyncOper(const std::string& hashCode, const int32_t operationType, + const int32_t matchType, const NotificationResponseBox &responseBox); + void DealMultiScreenSyncOper(const std::string& hashCode, const int32_t operationType, + const int32_t matchType, const NotificationResponseBox &responseBox); #else int32_t OnOperationResponse(const std::shared_ptr& operationInfo, const DistributedDeviceInfo& device); void ResponseOperationResult(const std::string& hashCode, const NotificationResponseBox& responseBox); + void LaunchProjectionApp(const DistributedDeviceInfo& device, const DistributedDeviceInfo& localDevice); #endif }; } diff --git a/services/distributed/include/soft_bus/distributed_publish_service.h b/services/distributed/include/soft_bus/distributed_publish_service.h index 44edf6a7a..7fae9ba15 100644 --- a/services/distributed/include/soft_bus/distributed_publish_service.h +++ b/services/distributed/include/soft_bus/distributed_publish_service.h @@ -43,7 +43,7 @@ public: private: void SyncNotifictionList(const DistributedDeviceInfo& peerDevice, const std::vector& notificationList); - void SetNotificationButtons(const sptr notificationRequest, + void SetNotificationButtons(const sptr notificationRequest, int32_t deviceType, NotificationConstant::SlotType slotType, std::shared_ptr& requestBox); void SetNotificationContent(const std::shared_ptr &content, NotificationContent::Type type, std::shared_ptr& requestBox); @@ -54,6 +54,7 @@ private: void MakeExtendInfo(const NotificationRequestBox& box, sptr& request); void MakeNotificationButtons(const NotificationRequestBox& box, NotificationConstant::SlotType slotType, sptr& request); + void MakePadNotificationButtons(const NotificationRequestBox& box, sptr& request); void MakeNotificationContent(const NotificationRequestBox& box, sptr& request, bool isCommonLiveView, int32_t contentType); void MakeNotificationIcon(const NotificationRequestBox& box, sptr& request, diff --git a/services/distributed/include/soft_bus/distributed_unlock_listener_oper_service.h b/services/distributed/include/soft_bus/distributed_unlock_listener_oper_service.h new file mode 100644 index 000000000..fbcc3d047 --- /dev/null +++ b/services/distributed/include/soft_bus/distributed_unlock_listener_oper_service.h @@ -0,0 +1,91 @@ +/* + * 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 BASE_NOTIFICATION_UNLOCK_LISTENER_TIMER_INFO_H +#define BASE_NOTIFICATION_UNLOCK_LISTENER_TIMER_INFO_H +#ifdef DISTRIBUTED_FEATURE_MASTER + +#include + +#include "ffrt.h" +#include "itimer_info.h" + +namespace OHOS { +namespace Notification { +struct UnlockListenerWant { + uint64_t timer; + std::shared_ptr wantAgentPtr = nullptr; +}; + +class UnlockListenerTimerInfo : public MiscServices::ITimerInfo { +public: + UnlockListenerTimerInfo(std::string timerHashCode) : timerHashCode_(timerHashCode) {}; + virtual ~UnlockListenerTimerInfo() {}; + /** + * When timing is up, this function will execute as call back. + */ + void OnTrigger() override; + + /** + * Indicates the timing type. + */ + void SetType(const int32_t &type) override {}; + + /** + * Indicates the repeat policy. + */ + void SetRepeat(bool repeat) override {}; + + /** + * Indicates the interval time for repeat timing. + */ + void SetInterval(const uint64_t &interval) override {}; + + /** + * Indicates the want agent information. + */ + void SetWantAgent(std::shared_ptr wantAgent) override {}; + +private: + std::string timerHashCode_; +}; + +class UnlockListenerOperService { +public: + static UnlockListenerOperService& GetInstance(); + void AddWantAgent(const std::string& hashCode, + const std::shared_ptr wantAgentPtr); + void ReplyOperationResponse(); + void HandleOperationTimeOut(const std::string& hashCode); + void RemoveOperationResponse(const std::string& hashCode); + ErrCode LaunchWantAgent(const std::shared_ptr wantAgentPtr); + +private: + UnlockListenerOperService(); + ~UnlockListenerOperService() = default; + + int64_t GetCurrentTime(); + +private: + std::mutex mapLock_; + std::shared_ptr operationQueue_ = nullptr; + std::vector hashCodeOrder_; + std::map timerMap_; + std::map> wantAgentMap_; +}; +} // namespace OHOS +} // namespace Notification +#endif // DISTRIBUTED_FEATURE_MASTER +#endif // BASE_NOTIFICATION_UNLOCK_LISTENER_TIMER_INFO_H diff --git a/services/distributed/include/tlv_box/request_box.h b/services/distributed/include/tlv_box/request_box.h index 331669b41..d74e33227 100644 --- a/services/distributed/include/tlv_box/request_box.h +++ b/services/distributed/include/tlv_box/request_box.h @@ -60,7 +60,9 @@ public: bool SetNotificationUserId(const int32_t& userId); bool SetDeviceUserId(const int32_t& userId); bool SetDeviceId(const std::string& deviceId); - + bool SetActionButtonsLength(const int32_t length); + bool SetActionButtonsTitle(const std::vector& buttonsTitle); + bool SetActionUserInputs(const std::vector& userInputs); #else bool GetNotificationHashCode(std::string& hasdCode) const; bool GetSlotType(int32_t& type) const; @@ -92,6 +94,9 @@ public: bool GetNotificationUserId(int32_t& userId) const; bool GetDeviceUserId(int32_t& userId) const; bool GetDeviceId(std::string& deviceId) const; + bool GetActionButtonsLength(int32_t& length) const; + bool GetActionButtonsTitle(std::vector& buttonsTitle) const; + bool GetActionUserInputs(std::vector& userInputs) const; #endif }; } // namespace Notification diff --git a/services/distributed/include/tlv_box/response_box.h b/services/distributed/include/tlv_box/response_box.h index 3b801346c..c0ac131fc 100644 --- a/services/distributed/include/tlv_box/response_box.h +++ b/services/distributed/include/tlv_box/response_box.h @@ -33,18 +33,22 @@ public: bool SetActionName(const std::string& actionName); bool SetUserInput(const std::string& userInput); bool SetOperationType(int32_t type); + bool SetOperationBtnIndex(int32_t index); bool SetMatchType(int32_t type); bool SetLocalDeviceId(const std::string& deviceId); bool SetResponseResult(int32_t result); + bool SetLocalDeviceType(const int32_t& deviceType); bool GetNotificationHashCode(std::string& hashCode) const; bool GetOperationEventId(std::string& eventId) const; bool GetActionName(std::string& actionName) const; bool GetUserInput(std::string& userInput) const; bool GetOperationType(int32_t& type) const; + bool GetOperationBtnIndex(int32_t& index) const; bool GetMatchType(int32_t& type) const; bool GetLocalDeviceId(std::string& deviceId) const; bool GetResponseResult(int32_t& result) const; + bool GetLocalDeviceType(int32_t& deviceType) const; }; } // namespace Notification } // namespace OHOS diff --git a/services/distributed/include/tlv_box/tlv_box.h b/services/distributed/include/tlv_box/tlv_box.h index fbb17f29a..302ce32ba 100644 --- a/services/distributed/include/tlv_box/tlv_box.h +++ b/services/distributed/include/tlv_box/tlv_box.h @@ -83,6 +83,10 @@ enum TlvType : int32_t { LOCAL_DEVICE_TYPE = 998, LOCAL_VERSION = 999, CHECK_SUM = 1000, + OPERATION_BTN_INDEX = 1001, + ACTION_BUTTONS_TITILE_INDEX = 1002, + ACTION_USER_INPUTS = 1005, + ACTION_BUTTONS_LENGTH = 1008, NOTIFICATION_ALL_LINES_START_INDEX = 2000, }; diff --git a/services/distributed/src/base/distributed_liveview_all_scenarios_extension_wrapper.cpp b/services/distributed/src/base/distributed_liveview_all_scenarios_extension_wrapper.cpp index 993f9372c..d06799a5b 100644 --- a/services/distributed/src/base/distributed_liveview_all_scenarios_extension_wrapper.cpp +++ b/services/distributed/src/base/distributed_liveview_all_scenarios_extension_wrapper.cpp @@ -69,6 +69,20 @@ void DistributedLiveviewAllScenariosExtensionWrapper::InitExtentionWrapper() ANS_LOGE("distributed unsubscribe all conncet failed, error: %{public}s", dlerror()); return; } + + liveViewMultiScreenSyncOper_ = + (LIVE_VIEW_MULTI_SCREEN_SYNC_OPER)dlsym(ExtensionHandle_, "LiveViewMultiScreenSyncOper"); + if (liveViewMultiScreenSyncOper_ == nullptr) { + ANS_LOGE("distributed liveView multi-Screen sync failed, error: %{public}s", dlerror()); + return; + } + + restoreCollaborationWindow_ = + (RESTORE_COLLABORATION_WINDOW)dlsym(ExtensionHandle_, "RestoreCollaborationWindow"); + if (restoreCollaborationWindow_ == nullptr) { + ANS_LOGE("distributed restore collaboration window failed, error: %{public}s", dlerror()); + return; + } ANS_LOGI("distributed liveview all scenarios extension wrapper init success"); } @@ -82,6 +96,8 @@ void DistributedLiveviewAllScenariosExtensionWrapper::CloseExtentionWrapper() triggerHandler_ = nullptr; updateLiveviewEncodeContent_ = nullptr; updateLiveviewDecodeContent_ = nullptr; + liveViewMultiScreenSyncOper_ = nullptr; + restoreCollaborationWindow_ = nullptr; } ANS_LOGI("distributed liveview all scenarios extension wrapper close success"); } @@ -133,4 +149,23 @@ ErrCode DistributedLiveviewAllScenariosExtensionWrapper::UnSubscribeAllConnect() } return unSubscribeHandler_(); } + +ErrCode DistributedLiveviewAllScenariosExtensionWrapper::LiveViewMultiScreenSyncOper( + sptr &request, const int32_t operationType, const int32_t btnIndex) +{ + if (liveViewMultiScreenSyncOper_ == nullptr) { + ANS_LOGE("liveView multi-Screen sync wrapper symbol failed"); + return 0; + } + return liveViewMultiScreenSyncOper_(request, operationType, btnIndex); +} + +int32_t DistributedLiveviewAllScenariosExtensionWrapper::RestoreCollaborationWindow(const std::string &networkId) +{ + if (restoreCollaborationWindow_ == nullptr) { + ANS_LOGE("restore collaboration window wrapper symbol failed"); + return 0; + } + return restoreCollaborationWindow_(networkId); +} } diff --git a/services/distributed/src/soft_bus/distributed_observer_service.cpp b/services/distributed/src/soft_bus/distributed_observer_service.cpp index 7eed738da..69d9e5e69 100644 --- a/services/distributed/src/soft_bus/distributed_observer_service.cpp +++ b/services/distributed/src/soft_bus/distributed_observer_service.cpp @@ -16,6 +16,7 @@ #include "distributed_service.h" #include "common_event_manager.h" +#include "distributed_unlock_listener_oper_service.h" #include "common_event_support.h" #include "distributed_operation_helper.h" @@ -48,6 +49,10 @@ void DistributedEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData DistributedService::GetInstance().HandleBundlesEvent(bundleName, action); return; } + if (action == EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_UNLOCKED) { + UnlockListenerOperService::GetInstance().ReplyOperationResponse(); + return; + } #else if (action == EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_LOCKED) { DistributedService::GetInstance().SyncDeviceStatus(SCREEN_OFF); @@ -86,6 +91,7 @@ void OberverService::Init(uint16_t deviceType) matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED); matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_UNLOCKED); #else if (deviceType == DistributedHardware::DmDeviceType::DEVICE_TYPE_PAD || deviceType == DistributedHardware::DmDeviceType::DEVICE_TYPE_2IN1 || diff --git a/services/distributed/src/soft_bus/distributed_operation_service.cpp b/services/distributed/src/soft_bus/distributed_operation_service.cpp index 336e31600..97fff6e4e 100644 --- a/services/distributed/src/soft_bus/distributed_operation_service.cpp +++ b/services/distributed/src/soft_bus/distributed_operation_service.cpp @@ -21,6 +21,7 @@ #include "notification_helper.h" #include "distributed_data_define.h" #include "distributed_device_service.h" +#include "distributed_unlock_listener_oper_service.h" #include "int_wrapper.h" #include "string_wrapper.h" #include "analytics_util.h" @@ -47,22 +48,22 @@ void DistributedOperationService::HandleNotificationOperation(const std::shared_ { int32_t operationType = 0; int32_t matchType = 0; + int32_t peerDeviceType = DistributedHardware::DmDeviceType::DEVICE_TYPE_WATCH; std::string hashCode; NotificationResponseBox responseBox = NotificationResponseBox(boxMessage); responseBox.GetOperationType(operationType); responseBox.GetMatchType(matchType); responseBox.GetNotificationHashCode(hashCode); - ANS_LOGI("handle response, hashCode: %{public}s type: %{public}d %{public}d.", - hashCode.c_str(), operationType, matchType); + responseBox.GetLocalDeviceType(peerDeviceType); + ANS_LOGI("handle response, hashCode: %{public}s, operationType: %{public}d, matchType: %{public}d \ + peerDeviceType: %{public}d.", hashCode.c_str(), operationType, matchType, peerDeviceType); #ifdef DISTRIBUTED_FEATURE_MASTER - if (matchType == MatchType::MATCH_SYN) { - if (static_cast(operationType) == OperationType::DISTRIBUTE_OPERATION_JUMP) { - TriggerJumpApplication(hashCode); - } else if (static_cast(operationType) == OperationType::DISTRIBUTE_OPERATION_REPLY) { - ErrCode result = TriggerReplyApplication(hashCode, responseBox); - ReplyOperationResponse(hashCode, responseBox, OperationType::DISTRIBUTE_OPERATION_REPLY, result); - } + if (peerDeviceType != DistributedHardware::DmDeviceType::DEVICE_TYPE_PAD && + peerDeviceType != DistributedHardware::DmDeviceType::DEVICE_TYPE_PC) { + DealNonMultiScreenSyncOper(hashCode, operationType, matchType, responseBox); + return; } + DealMultiScreenSyncOper(hashCode, operationType, matchType, responseBox); #else if (matchType == MatchType::MATCH_ACK) { ResponseOperationResult(hashCode, responseBox); @@ -146,6 +147,47 @@ static ErrCode GetNotificationButtonWantPtr(const std::string& hashCode, const s return ERR_OK; } +static ErrCode GetNotificationButtonWantAgentPtr(const std::string& hashCode, + const int32_t btnIndex, std::shared_ptr& wantAgentPtr) +{ + sptr notificationRequest = nullptr; + auto result = NotificationHelper::GetNotificationRequestByHashCode(hashCode, notificationRequest); + if (result != ERR_OK || notificationRequest == nullptr) { + ANS_LOGE("Check notificationRequest is null."); + return ERR_ANS_NOTIFICATION_NOT_EXISTS; + } + + auto actionButtons = notificationRequest->GetActionButtons(); + if (actionButtons.empty() || actionButtons.size() <= static_cast(btnIndex)) { + ANS_LOGE("Check actionButtons is null."); + return ERR_ANS_INVALID_PARAM; + } + + auto clickedBtn = actionButtons[btnIndex]; + if (clickedBtn == nullptr) { + ANS_LOGE("NotificationRequest button is invalid, btnIndex: %{public}d.", btnIndex); + return ERR_ANS_INVALID_PARAM; + } + + wantAgentPtr = clickedBtn->GetWantAgent(); + if (wantAgentPtr == nullptr) { + ANS_LOGE("Check wantAgentPtr is null."); + return ERR_ANS_INVALID_PARAM; + } + return ERR_OK; +} + +static std::shared_ptr GetNotificationWantAgentPtr(const std::string& hashCode) +{ + sptr notificationRequest = nullptr; + auto result = NotificationHelper::GetNotificationRequestByHashCode(hashCode, notificationRequest); + if (result != ERR_OK || notificationRequest == nullptr) { + ANS_LOGE("Check notificationRequest is null."); + return nullptr; + } + return notificationRequest->GetWantAgent(); +} + static std::shared_ptr GetNotificationWantPtr(const std::string& hashCode) { sptr notificationRequest = nullptr; @@ -287,6 +329,67 @@ void DistributedOperationService::TriggerJumpApplication(const std::string& hash AnalyticsUtil::GetInstance().AbnormalReporting(MODIFY_ERROR_EVENT_CODE, ret, BRANCH9_ID, "pull up success"); } } + +void DistributedOperationService::DealNonMultiScreenSyncOper(const std::string& hashCode, + const int32_t operationType, const int32_t matchType, const NotificationResponseBox &responseBox) +{ + if (matchType != MatchType::MATCH_SYN) { + return; + } + if (static_cast(operationType) == OperationType::DISTRIBUTE_OPERATION_JUMP) { + TriggerJumpApplication(hashCode); + } else if (static_cast(operationType) == OperationType::DISTRIBUTE_OPERATION_REPLY) { + ErrCode result = TriggerReplyApplication(hashCode, responseBox); + ReplyOperationResponse(hashCode, responseBox, OperationType::DISTRIBUTE_OPERATION_REPLY, result); + } +} + +void DistributedOperationService::DealMultiScreenSyncOper(const std::string& hashCode, + const int32_t operationType, const int32_t matchType, const NotificationResponseBox &responseBox) +{ + if (matchType != MatchType::MATCH_SYN) { + return; + } + std::shared_ptr wantAgentPtr = nullptr; + if (operationType >= static_cast(OperationType::DISTRIBUTE_OPERATION_FOR_LIVE_VIEW)) { + sptr notificationRequest = nullptr; + auto result = NotificationHelper::GetNotificationRequestByHashCode(hashCode, notificationRequest); + if (result != ERR_OK || notificationRequest == nullptr) { + ANS_LOGE("Check notificationRequest is null."); + return; + } + if (!notificationRequest->IsCommonLiveView()) { + ANS_LOGE("operationType for liveView but notification not liveView."); + return; + } + int32_t btnIndex; + responseBox.GetOperationBtnIndex(btnIndex); + ErrCode res = DISTRIBUTED_LIVEVIEW_ALL_SCENARIOS_EXTENTION_WRAPPER->LiveViewMultiScreenSyncOper( + notificationRequest, operationType, btnIndex); + ANS_LOGI("LiveViewMultiScreenSyncOper res: %{public}d.", static_cast(res)); + return; + } else if (static_cast(operationType) == OperationType::DISTRIBUTE_OPERATION_JUMP) { + wantAgentPtr = GetNotificationWantAgentPtr(hashCode); + } else if (static_cast(operationType) == OperationType::DISTRIBUTE_OPERATION_REPLY) { + int32_t btnIndex; + responseBox.GetOperationBtnIndex(btnIndex); + GetNotificationButtonWantAgentPtr(hashCode, btnIndex, wantAgentPtr); + } + + if (wantAgentPtr == nullptr) { + ANS_LOGE("DealMultiScreenSyncOper fail cause wantAgentPtr is null."); + return; + } + if (!ScreenLock::ScreenLockManager::GetInstance()->IsScreenLocked() && + UnlockListenerOperService::GetInstance().LaunchWantAgent(wantAgentPtr) == ERR_OK) { + std::vector hashcodes; + hashcodes.push_back(hashCode); + NotificationHelper::RemoveNotifications( + hashcodes, NotificationConstant::DISTRIBUTED_COLLABORATIVE_CLICK_DELETE); + return; + } + UnlockListenerOperService::GetInstance().AddWantAgent(hashCode, wantAgentPtr); +} #else int32_t DistributedOperationService::OnOperationResponse( @@ -308,6 +411,10 @@ int32_t DistributedOperationService::OnOperationResponse( ANS_LOGW("dans OnResponse SetMessageType failed"); return ERR_ANS_TASK_ERR; } + ANS_LOGI("dans OnResponse clicked btnIndex: %{public}d", operationInfo->GetBtnIndex()); + if (0 <= operationInfo->GetBtnIndex() && operationInfo->GetBtnIndex() < NotificationConstant::MAX_BTN_NUM) { + responseBox->SetOperationBtnIndex(operationInfo->GetBtnIndex()); + } responseBox->SetActionName(operationInfo->GetActionName()); responseBox->SetUserInput(operationInfo->GetUserInput()); } @@ -318,11 +425,13 @@ int32_t DistributedOperationService::OnOperationResponse( responseBox->SetNotificationHashCode(hashCode); responseBox->SetOperationEventId(operationInfo->GetEventId()); responseBox->SetLocalDeviceId(localDevice.deviceId_); + responseBox->SetLocalDeviceType(localDevice.deviceType_); if (!responseBox->Serialize()) { ANS_LOGW("dans OnResponse serialize failed"); return ERR_ANS_TASK_ERR; } + LaunchProjectionApp(device, localDevice); auto result = DistributedClient::GetInstance().SendMessage(responseBox, TransDataType::DATA_TYPE_MESSAGE, device.deviceId_, MODIFY_ERROR_EVENT_CODE); if (result != ERR_OK) { @@ -343,6 +452,21 @@ void DistributedOperationService::ResponseOperationResult(const std::string& has ANS_LOGI("HandleOperationResponse hashcode %{public}s, result:%{public}d %{public}d", hashCode.c_str(), result, ret); } + +void DistributedOperationService::LaunchProjectionApp( + const DistributedDeviceInfo& device, const DistributedDeviceInfo& localDevice) +{ + if ((localDevice.deviceType_ != DistributedHardware::DmDeviceType::DEVICE_TYPE_PAD && + localDevice.deviceType_ != DistributedHardware::DmDeviceType::DEVICE_TYPE_PC) || + device.deviceType_ != DistributedHardware::DmDeviceType::DEVICE_TYPE_PHONE) { + ANS_LOGI("Can not launch projectionApp"); + return; + } + int32_t result = + DISTRIBUTED_LIVEVIEW_ALL_SCENARIOS_EXTENTION_WRAPPER->RestoreCollaborationWindow(device.networkId_); + ANS_LOGI("RestoreCollaborationWindow result: %{public}d, networkId: %{public}s", + result, device.networkId_.c_str()); +} #endif } } diff --git a/services/distributed/src/soft_bus/distributed_publish_service_v2.cpp b/services/distributed/src/soft_bus/distributed_publish_service_v2.cpp index f38eb26af..22b32a156 100644 --- a/services/distributed/src/soft_bus/distributed_publish_service_v2.cpp +++ b/services/distributed/src/soft_bus/distributed_publish_service_v2.cpp @@ -258,7 +258,7 @@ void DistributedPublishService::SendNotifictionRequest(const std::shared_ptrSetCommonLiveView(buffer); } SetNotificationExtendInfo(requestPoint, peerDevice.deviceType_, requestBox); - SetNotificationButtons(requestPoint, requestPoint->GetSlotType(), requestBox); + SetNotificationButtons(requestPoint, peerDevice.deviceType_, requestPoint->GetSlotType(), requestBox); SetNotificationContent(request->GetNotificationRequestPoint()->GetContent(), requestPoint->GetNotificationType(), requestBox); if (!requestBox->Serialize()) { @@ -326,15 +326,41 @@ void DistributedPublishService::SetNotificationContent(const std::shared_ptr notificationRequest, - NotificationConstant::SlotType slotType, std::shared_ptr& requestBox) + int32_t deviceType, NotificationConstant::SlotType slotType, std::shared_ptr& requestBox) { - if (slotType == NotificationConstant::SlotType::SOCIAL_COMMUNICATION) { - auto actionButtons = notificationRequest->GetActionButtons(); - if (actionButtons.empty()) { - ANS_LOGE("Check actionButtons is null."); + auto actionButtons = notificationRequest->GetActionButtons(); + if (actionButtons.empty()) { + ANS_LOGE("Check actionButtons is null."); + return; + } + if (deviceType == DistributedHardware::DmDeviceType::DEVICE_TYPE_PAD || + deviceType == DistributedHardware::DmDeviceType::DEVICE_TYPE_PC) { + if (notificationRequest->IsCommonLiveView()) { return; } - + std::vector buttonsTitle; + std::vector userInputs; + size_t length = actionButtons.size(); + if (length > NotificationConstant::MAX_BTN_NUM) { + length = NotificationConstant::MAX_BTN_NUM; + } + for (size_t i = 0; i < length; i++) { + if (actionButtons[i] == nullptr) { + return; + } + buttonsTitle.push_back(actionButtons[i]->GetTitle()); + std::string inputKey = ""; + if (actionButtons[i]->GetUserInput() != nullptr) { + userInputs.push_back(actionButtons[i]->GetUserInput()->GetInputKey()); + } else { + userInputs.push_back(inputKey); + } + } + requestBox->SetActionButtonsTitle(buttonsTitle); + requestBox->SetActionUserInputs(userInputs); + return; + } + if (slotType == NotificationConstant::SlotType::SOCIAL_COMMUNICATION) { std::shared_ptr button = nullptr; for (std::shared_ptr buttonItem : actionButtons) { if (buttonItem != nullptr && buttonItem->GetUserInput() != nullptr && @@ -472,6 +498,13 @@ void DistributedPublishService::PublishSynchronousLiveView(const std::shared_ptr void DistributedPublishService::MakeNotificationButtons(const NotificationRequestBox& box, NotificationConstant::SlotType slotType, sptr& request) { + auto localDevice = DistributedDeviceService::GetInstance().GetLocalDevice(); + if ((localDevice.deviceType_ == DistributedHardware::DmDeviceType::DEVICE_TYPE_PAD || + localDevice.deviceType_ == DistributedHardware::DmDeviceType::DEVICE_TYPE_PC)) { + MakePadNotificationButtons(box, request); + return; + } + if (request != nullptr && slotType == NotificationConstant::SlotType::SOCIAL_COMMUNICATION) { std::string actionName; std::string userInputKey; @@ -493,6 +526,38 @@ void DistributedPublishService::MakeNotificationButtons(const NotificationReques } } +void DistributedPublishService::MakePadNotificationButtons( + const NotificationRequestBox& box, sptr& request) +{ + if (request == nullptr || request->IsCommonLiveView()) { + return; + } + std::vector buttonsTitle; + std::vector userInputs; + if (!box.GetActionButtonsTitle(buttonsTitle) || + !box.GetActionUserInputs(userInputs) || buttonsTitle.size() <= 0) { + ANS_LOGI("Notification [hashCode: %{public}s] has no button.", request->GetNotificationHashCode().c_str()); + return; + } + if (buttonsTitle.size() != userInputs.size()) { + ANS_LOGE("Notification [hashCode: %{public}s] inner error, button property size not same.", + request->GetNotificationHashCode().c_str()); + return; + } + for (size_t i = 0; i < buttonsTitle.size(); i++) { + std::shared_ptr actionButton = + NotificationActionButton::Create(nullptr, buttonsTitle[i], nullptr); + std::shared_ptr userInput; + if (userInputs[i].length() > 0) { + userInput = NotificationUserInput::Create(userInputs[i]); + } + if (userInput) { + actionButton->AddNotificationUserInput(userInput); + } + request->AddActionButton(actionButton); + } +} + void DistributedPublishService::MakeNotificationReminderFlag(const NotificationRequestBox& box, sptr& request) { diff --git a/services/distributed/src/soft_bus/distributed_unlock_listener_oper_service.cpp b/services/distributed/src/soft_bus/distributed_unlock_listener_oper_service.cpp new file mode 100644 index 000000000..8bf7fff15 --- /dev/null +++ b/services/distributed/src/soft_bus/distributed_unlock_listener_oper_service.cpp @@ -0,0 +1,177 @@ +/* + * 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. + */ + +#ifdef DISTRIBUTED_FEATURE_MASTER +#include "distributed_unlock_listener_oper_service.h" + +#include "ans_log_wrapper.h" +#include "notification_constant.h" +#include "notification_helper.h" +#include "time_service_client.h" + +namespace OHOS { +namespace Notification { +namespace { + static const int64_t OPERATION_TIMEOUT = 30 * 1000; +} +void UnlockListenerTimerInfo::OnTrigger() +{ + UnlockListenerOperService::GetInstance().HandleOperationTimeOut(timerHashCode_); +} + +UnlockListenerOperService& UnlockListenerOperService::GetInstance() +{ + static UnlockListenerOperService unlockListenerOperService; + return unlockListenerOperService; +} + +UnlockListenerOperService::UnlockListenerOperService() +{ + operationQueue_ = std::make_shared("ans_operation"); + if (operationQueue_ == nullptr) { + ANS_LOGE("ffrt create failed!"); + return; + } + ANS_LOGI("Operation service init successfully."); +} + +void UnlockListenerOperService::AddWantAgent(const std::string& hashCode, + const std::shared_ptr wantAgentPtr) +{ + int32_t timeout = OPERATION_TIMEOUT; + int64_t expiredTime = GetCurrentTime() + timeout; + std::shared_ptr timerInfo = std::make_shared(hashCode); + sptr timer = MiscServices::TimeServiceClient::GetInstance(); + if (timer == nullptr) { + ANS_LOGE("Failed to start timer due to get TimeServiceClient is null."); + return; + } + uint64_t timerId = timer->CreateTimer(timerInfo); + timer->StartTimer(timerId, expiredTime); + std::lock_guard lock(mapLock_); + auto iterWantAgent = wantAgentMap_.find(hashCode); + if (iterWantAgent != wantAgentMap_.end()) { + ANS_LOGW("Operation wantAgent has same key %{public}s.", hashCode.c_str()); + wantAgentMap_.erase(iterWantAgent); + } + wantAgentMap_.insert_or_assign(hashCode, wantAgentPtr); + + auto iterTimer = timerMap_.find(hashCode); + if (iterTimer != timerMap_.end()) { + ANS_LOGW("Operation timer has same key %{public}s.", hashCode.c_str()); + if (iterTimer->second == NotificationConstant::INVALID_TIMER_ID) { + return; + } + MiscServices::TimeServiceClient::GetInstance()->StopTimer(iterTimer->second); + MiscServices::TimeServiceClient::GetInstance()->DestroyTimer(iterTimer->second); + timerMap_.erase(iterTimer); + } + timerMap_.insert_or_assign(hashCode, timerId); + auto iterOder = std::find(hashCodeOrder_.begin(), hashCodeOrder_.end(), hashCode); + if (iterOder != hashCodeOrder_.end()) { + hashCodeOrder_.erase(iterOder); + } + hashCodeOrder_.push_back(hashCode); + ANS_LOGI("Operation add key %{public}s.", hashCode.c_str()); +} + +void UnlockListenerOperService::RemoveOperationResponse(const std::string& hashCode) +{ + std::lock_guard lock(mapLock_); + auto iterWantAgent = wantAgentMap_.find(hashCode); + if (iterWantAgent != wantAgentMap_.end()) { + wantAgentMap_.erase(iterWantAgent); + ANS_LOGI("Operation wantAgent erase %{public}s", hashCode.c_str()); + } + + auto iterTimer = timerMap_.find(hashCode); + if (iterTimer != timerMap_.end()) { + if (iterTimer->second == NotificationConstant::INVALID_TIMER_ID) { + return; + } + ANS_LOGI("Operation timer erase %{public}s %{public}llu", hashCode.c_str(), iterTimer->second); + MiscServices::TimeServiceClient::GetInstance()->StopTimer(iterTimer->second); + MiscServices::TimeServiceClient::GetInstance()->DestroyTimer(iterTimer->second); + timerMap_.erase(iterTimer); + } + auto iterOder = std::find(hashCodeOrder_.begin(), hashCodeOrder_.end(), hashCode); + if (iterOder != hashCodeOrder_.end()) { + hashCodeOrder_.erase(iterOder); + } +} + +void UnlockListenerOperService::ReplyOperationResponse() +{ + std::lock_guard lock(mapLock_); + ANS_LOGI("UnlockListenerOperService ReplyOperationResponse hashCodeOrder size %{public}u", hashCodeOrder_.size()); + std::vector hashcodesToDel; + for (std::string hashCode : hashCodeOrder_) { + auto iterWantAgent = wantAgentMap_.find(hashCode); + if (iterWantAgent != wantAgentMap_.end()) { + if (LaunchWantAgent(iterWantAgent->second) == ERR_OK) { + hashcodesToDel.push_back(hashCode); + } + wantAgentMap_.erase(iterWantAgent); + } + + auto iterTimer = timerMap_.find(hashCode); + if (iterTimer != timerMap_.end()) { + if (iterTimer->second == NotificationConstant::INVALID_TIMER_ID) { + return; + } + MiscServices::TimeServiceClient::GetInstance()->StopTimer(iterTimer->second); + MiscServices::TimeServiceClient::GetInstance()->DestroyTimer(iterTimer->second); + timerMap_.erase(iterTimer); + } + } + NotificationHelper::RemoveNotifications( + hashcodesToDel, NotificationConstant::DISTRIBUTED_COLLABORATIVE_CLICK_DELETE); + hashCodeOrder_.clear(); +} + +void UnlockListenerOperService::HandleOperationTimeOut(const std::string& hashCode) +{ + if (operationQueue_ == nullptr) { + ANS_LOGE("Operation queue is invalid."); + return; + } + + ANS_LOGI("HandleOperationTimeOut hashCode: %{public}s", hashCode.c_str()); + operationQueue_->submit_h([&, hashCode]() { + RemoveOperationResponse(hashCode); + }); +} + +ErrCode UnlockListenerOperService::LaunchWantAgent( + const std::shared_ptr wantAgentPtr) +{ + std::shared_ptr want = std::make_shared(); + OHOS::AbilityRuntime::WantAgent::TriggerInfo triggerInfo("", nullptr, want, 0); + sptr data; + ErrCode res = + AbilityRuntime::WantAgent::WantAgentHelper::TriggerWantAgent(wantAgentPtr, nullptr, triggerInfo, data, nullptr); + ANS_LOGI("LaunchWantAgent result: %{public}d.", static_cast(res)); + return res; +} + +int64_t UnlockListenerOperService::GetCurrentTime() +{ + auto now = std::chrono::system_clock::now(); + auto duration = std::chrono::duration_cast(now.time_since_epoch()); + return duration.count(); +} +} +} +#endif diff --git a/services/distributed/src/tlv_box/request_box.cpp b/services/distributed/src/tlv_box/request_box.cpp index 1d400491c..bd4caee3d 100644 --- a/services/distributed/src/tlv_box/request_box.cpp +++ b/services/distributed/src/tlv_box/request_box.cpp @@ -323,6 +323,41 @@ bool NotificationRequestBox::SetDeviceId(const std::string& deviceId) return box_->PutValue(std::make_shared(LOCAL_DEVICE_ID, deviceId)); } +bool NotificationRequestBox::SetActionButtonsLength(const int32_t length) +{ + if (box_ == nullptr) { + return false; + } + return box_->PutValue(std::make_shared(ACTION_BUTTONS_LENGTH, length)); +} + +bool NotificationRequestBox::SetActionButtonsTitle(const std::vector& buttonsTitle) +{ + if (box_ == nullptr) { + return false; + } + int32_t index = 0; + for (auto& buttonTitle : buttonsTitle) { + if (box_->PutValue( + std::make_shared(ACTION_BUTTONS_TITILE_INDEX + index, buttonTitle))) { + index++; + } + } + return SetActionButtonsLength(index); +} + +bool NotificationRequestBox::SetActionUserInputs(const std::vector& userInputs) +{ + if (box_ == nullptr) { + return false; + } + for (size_t i = 0; i < userInputs.size(); i++) { + box_->PutValue( + std::make_shared(ACTION_USER_INPUTS + i, userInputs[i])); + } + return true; +} + #else bool NotificationRequestBox::GetNotificationHashCode(std::string& hasdCode) const { @@ -585,6 +620,48 @@ bool NotificationRequestBox::GetDeviceId(std::string& deviceId) const } return box_->GetStringValue(LOCAL_DEVICE_ID, deviceId); } + +bool NotificationRequestBox::GetActionButtonsLength(int32_t& length) const +{ + if (box_ == nullptr) { + return false; + } + return box_->GetInt32Value(ACTION_BUTTONS_LENGTH, length); +} + +bool NotificationRequestBox::GetActionButtonsTitle(std::vector& buttonsTitle) const +{ + if (box_ == nullptr) { + return false; + } + int32_t length = 0; + if (!GetActionButtonsLength(length)) { + return false; + } + for (int i = 0; i < length; i++) { + std::string buttonTitle = ""; + box_->GetStringValue(ACTION_BUTTONS_TITILE_INDEX + i, buttonTitle); + buttonsTitle.push_back(buttonTitle); + } + return true; +} + +bool NotificationRequestBox::GetActionUserInputs(std::vector& userInputs) const +{ + if (box_ == nullptr) { + return false; + } + int32_t length = 0; + if (!GetActionButtonsLength(length)) { + return false; + } + for (int i = 0; i < length; i++) { + std::string userInput = ""; + box_->GetStringValue(ACTION_USER_INPUTS + i, userInput); + userInputs.push_back(userInput); + } + return true; +} #endif } } diff --git a/services/distributed/src/tlv_box/response_box.cpp b/services/distributed/src/tlv_box/response_box.cpp index ab707c5ff..93d5fd34b 100644 --- a/services/distributed/src/tlv_box/response_box.cpp +++ b/services/distributed/src/tlv_box/response_box.cpp @@ -76,6 +76,14 @@ bool NotificationResponseBox::SetOperationType(int32_t type) return box_->PutValue(std::make_shared(OPERATION_TYPE, type)); } +bool NotificationResponseBox::SetOperationBtnIndex(int32_t index) +{ + if (box_ == nullptr) { + return false; + } + return box_->PutValue(std::make_shared(OPERATION_BTN_INDEX, index)); +} + bool NotificationResponseBox::SetMatchType(int32_t type) { if (box_ == nullptr) { @@ -100,6 +108,14 @@ bool NotificationResponseBox::SetResponseResult(int32_t result) return box_->PutValue(std::make_shared(RESULT_CODE, result)); } +bool NotificationResponseBox::SetLocalDeviceType(const int32_t& deviceType) +{ + if (box_ == nullptr) { + return false; + } + return box_->PutValue(std::make_shared(LOCAL_DEVICE_TYPE, deviceType)); +} + bool NotificationResponseBox::GetNotificationHashCode(std::string& hashCode) const { if (box_ == nullptr) { @@ -140,6 +156,14 @@ bool NotificationResponseBox::GetOperationType(int32_t& type) const return box_->GetInt32Value(OPERATION_TYPE, type); } +bool NotificationResponseBox::GetOperationBtnIndex(int32_t& index) const +{ + if (box_ == nullptr) { + return false; + } + return box_->GetInt32Value(OPERATION_BTN_INDEX, index); +} + bool NotificationResponseBox::GetMatchType(int32_t& type) const { if (box_ == nullptr) { @@ -163,5 +187,13 @@ bool NotificationResponseBox::GetResponseResult(int32_t& result) const } return box_->GetInt32Value(RESULT_CODE, result); } + +bool NotificationResponseBox::GetLocalDeviceType(int32_t& deviceType) const +{ + if (box_ == nullptr) { + return false; + } + return box_->GetInt32Value(LOCAL_DEVICE_TYPE, deviceType); +} } // namespace Notification } // namespace OHOS -- Gitee