diff --git a/frameworks/ans/src/notification_request.cpp b/frameworks/ans/src/notification_request.cpp index b43e9fcb0be3192de8ec3dab5f84196e892d0394..9047e0d6b6e67e24a5adcd1130f934b0d538ab82 100644 --- a/frameworks/ans/src/notification_request.cpp +++ b/frameworks/ans/src/notification_request.cpp @@ -2788,6 +2788,13 @@ void NotificationRequest::FillMissingParameters(const sptr NotificationLiveViewContent::LiveViewStatus::LIVE_VIEW_FULL_UPDATE) { return; } + IncrementalUpdateLiveview(oldRequest); +} + +void NotificationRequest::IncrementalUpdateLiveview(const sptr &oldRequest) +{ + auto content = notificationContent_->GetNotificationContent(); + auto newLiveViewContent = std::static_pointer_cast(content); auto newExtraInfo = newLiveViewContent->GetExtraInfo(); auto oldContent = oldRequest->GetContent()->GetNotificationContent(); auto oldLiveViewContent = std::static_pointer_cast(oldContent); @@ -2821,6 +2828,11 @@ void NotificationRequest::FillMissingParameters(const sptr if (isSet) { newLiveViewContent->SetPicture(newPicture); } + + auto oldExtensionWantAgent = oldLiveViewContent->GetExtensionWantAgent(); + if (newLiveViewContent->GetExtensionWantAgent() == nullptr) { + newLiveViewContent->SetExtensionWantAgent(oldExtensionWantAgent); + } } std::string NotificationRequest::GetBaseKey(const std::string &deviceId) diff --git a/frameworks/js/napi/src/common_convert_liveview.cpp b/frameworks/js/napi/src/common_convert_liveview.cpp index 301699d957e48019ad2c7c2fd533e7a1739210f1..fdceb58c006a55ed084f530ce4b81427dff5444e 100644 --- a/frameworks/js/napi/src/common_convert_liveview.cpp +++ b/frameworks/js/napi/src/common_convert_liveview.cpp @@ -426,16 +426,15 @@ napi_value Common::SetNotificationLiveViewContent( // pictureInfo?: {[key, string]: Array} if (liveViewContent->GetPicture().empty()) { - ANS_LOGD("No pictures in live view."); - return NapiGetBoolean(env, true); - } - - napi_value pictureMapObj = SetLiveViewPictureInfo(env, liveViewContent->GetPicture()); - if (pictureMapObj == nullptr) { - ANS_LOGE("null pictureMapObj"); - return NapiGetBoolean(env, false); + ANS_LOGE("No pictures in live view."); + } else { + napi_value pictureMapObj = SetLiveViewPictureInfo(env, liveViewContent->GetPicture()); + if (pictureMapObj == nullptr) { + ANS_LOGE("null pictureMapObj"); + return NapiGetBoolean(env, false); + } + napi_set_named_property(env, result, "pictureInfo", pictureMapObj); } - napi_set_named_property(env, result, "pictureInfo", pictureMapObj); std::shared_ptr agent = liveViewContent->GetExtensionWantAgent(); if (agent) { @@ -1269,15 +1268,14 @@ napi_value Common::GetNotificationLiveViewContentDetailed( jsValue = AppExecFwk::GetPropertyValueByPropertyName(env, contentResult, "pictureInfo", napi_object); if (jsValue == nullptr) { ANS_LOGE("null jsValue"); - return NapiGetNull(env); - } - - std::map>> pictureMap; - if (GetLiveViewPictureInfo(env, jsValue, pictureMap) == nullptr) { - ANS_LOGE("null LiveViewPictureInfo"); - return nullptr; + } else { + std::map>> pictureMap; + if (GetLiveViewPictureInfo(env, jsValue, pictureMap) == nullptr) { + ANS_LOGE("null LiveViewPictureInfo"); + return nullptr; + } + liveViewContent->SetPicture(pictureMap); } - liveViewContent->SetPicture(pictureMap); if (GetLiveViewWantAgent(env, contentResult, liveViewContent) == nullptr) { ANS_LOGD("no live view wantAgent"); diff --git a/services/ans/include/notification_rdb_data_mgr.h b/services/ans/include/notification_rdb_data_mgr.h index 6e49a8c198247c2479d5282981f5a7095ac42534..306efc9779966b31e23525d6cb76f6fad62e2b41 100644 --- a/services/ans/include/notification_rdb_data_mgr.h +++ b/services/ans/include/notification_rdb_data_mgr.h @@ -23,6 +23,7 @@ #include #include #include "notification_constant.h" +#include "notification_request.h" #include "rdb_errno.h" #include "rdb_helper.h" #include "rdb_open_callback.h" @@ -55,6 +56,27 @@ public: int32_t OnOpen(NativeRdb::RdbStore &rdbStore) override; int32_t onCorruption(std::string databaseFile) override; + + std::set GetTableNames(NativeRdb::RdbStore &rdbStore); + + bool ProcessTable(NativeRdb::RdbStore &rdbStore, const std::string &tableName); + + bool UpdateRequest(NotificationRequest *request); + + std::shared_ptr QueryTable(NativeRdb::RdbStore &rdbStore, + const std::string &tableName); + + bool ProcessResultSet(std::shared_ptr absSharedResultSet, + NativeRdb::RdbStore &rdbStore, const std::string &tableName); + + bool ProcessRow(std::shared_ptr absSharedResultSet, + NativeRdb::RdbStore &rdbStore, const std::string &tableName); + + bool GetStringFromResultSet(std::shared_ptr absSharedResultSet, + int columnIndex, std::string &result); + + bool WriteBackToDatabase(NotificationRequest *request, NotificationBundleOption *bundleOption, + NativeRdb::RdbStore &rdbStore, const std::string &tableName); private: NotificationRdbConfig notificationRdbConfig_; bool hasTableInit_ = false; diff --git a/services/ans/src/notification_rdb_data_mgr.cpp b/services/ans/src/notification_rdb_data_mgr.cpp index 62924f79e1a14fc18d80ec8f814f0710960cb617..36333bb5e5b0bc3135592a01f1881e0cc5170d43 100644 --- a/services/ans/src/notification_rdb_data_mgr.cpp +++ b/services/ans/src/notification_rdb_data_mgr.cpp @@ -23,6 +23,8 @@ #include #include #include "notification_analytics_util.h" +#include "notification_preferences.h" +#include "aes_gcm_helper.h" namespace OHOS { namespace Notification { @@ -33,6 +35,7 @@ const int32_t NOTIFICATION_KEY_INDEX = 0; const int32_t NOTIFICATION_VALUE_INDEX = 1; const std::ptrdiff_t MAX_SIZE_PER_BATCH = 100; const int32_t NOTIFICATION_RDB_MAX_MEMORY_SIZE = 1; +const std::string LIVE_VIEW_KEY = "secure_live_view"; } // namespace RdbStoreDataCallBackNotificationStorage::RdbStoreDataCallBackNotificationStorage( const NotificationRdbConfig ¬ificationRdbConfig): notificationRdbConfig_(notificationRdbConfig) @@ -67,8 +70,194 @@ int32_t RdbStoreDataCallBackNotificationStorage::OnUpgrade( { ANS_LOGD("OnUpgrade currentVersion: %{public}d, targetVersion: %{public}d", oldVersion, newVersion); + + if (oldVersion == 1) { + std::set tables = GetTableNames(rdbStore); + if (tables.empty()) { + } + + for (const std::string &tableName : tables) { + ANS_LOGE("wfr table is %{public}s", tableName.c_str()); + if (!ProcessTable(rdbStore, tableName)) { + } + } + } + return NativeRdb::E_OK; } + +std::set RdbStoreDataCallBackNotificationStorage::GetTableNames(NativeRdb::RdbStore &rdbStore) +{ + std::set tables; + std::string queryTableSql = "SELECT name FROM sqlite_master WHERE type='table'"; + auto absSharedResultSet = rdbStore.QuerySql(queryTableSql); + if (absSharedResultSet == nullptr) { + ANS_LOGE("Query tableName failed"); + return tables; + } + int32_t ret = absSharedResultSet->GoToFirstRow(); + if (ret != NativeRdb::E_OK) { + ANS_LOGE("Query tableName failed. It's empty!"); + return tables; + } + + do { + std::string tableName; + ret = absSharedResultSet->GetString(0, tableName); + if (ret == NativeRdb::E_OK) { + tables.insert(tableName); + } + } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK); + + return tables; +} + +bool RdbStoreDataCallBackNotificationStorage::ProcessTable( + NativeRdb::RdbStore &rdbStore, const std::string &tableName) +{ + auto absSharedResultSet = QueryTable(rdbStore, tableName); + if (!absSharedResultSet) { + return false; + } + + bool result = ProcessResultSet(absSharedResultSet, rdbStore, tableName); + absSharedResultSet->Close(); + return result; +} + +std::shared_ptr RdbStoreDataCallBackNotificationStorage::QueryTable( + NativeRdb::RdbStore &rdbStore, const std::string &tableName) +{ + NativeRdb::AbsRdbPredicates absRdbPredicates(tableName); + absRdbPredicates.BeginsWith(NOTIFICATION_KEY, LIVE_VIEW_KEY); + auto absSharedResultSet = rdbStore.Query(absRdbPredicates, std::vector()); + if (!absSharedResultSet) { + ANS_LOGE("absSharedResultSet failed from %{public}s table.", tableName.c_str()); + } + return absSharedResultSet; +} + +bool RdbStoreDataCallBackNotificationStorage::ProcessResultSet( + std::shared_ptr absSharedResultSet, + NativeRdb::RdbStore &rdbStore, const std::string &tableName) +{ + absSharedResultSet->GoToFirstRow(); + do { + if (!ProcessRow(absSharedResultSet, rdbStore, tableName)) { + return false; + } + } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK); + + return true; +} + +bool RdbStoreDataCallBackNotificationStorage::ProcessRow( + std::shared_ptr absSharedResultSet, + NativeRdb::RdbStore &rdbStore, const std::string &tableName) +{ + std::string resultKey; + if (!GetStringFromResultSet(absSharedResultSet, NOTIFICATION_KEY_INDEX, resultKey)) { + return false; + } + + std::string resultValue; + if (!GetStringFromResultSet(absSharedResultSet, NOTIFICATION_VALUE_INDEX, resultValue)) { + return false; + } + + std::string input; + AesGcmHelper::Decrypt(input, resultValue); + auto jsonObject = nlohmann::json::parse(input); + + auto *request = NotificationJsonConverter::ConvertFromJson(jsonObject); + if (!request) { + ANS_LOGE("Parse json string to request failed."); + return true; + } + + auto *bundleOption = NotificationJsonConverter::ConvertFromJson(jsonObject); + if (!bundleOption) { + ANS_LOGE("Parse json string to bundleOption failed."); + return true; + } + + ANS_LOGW("before request: %{public}s.", request->Dump().c_str()); + if (!UpdateRequest(request)) { + return true; + } + + if (!WriteBackToDatabase(request, bundleOption, rdbStore, tableName)) { + return false; + } + + return true; +} + +bool RdbStoreDataCallBackNotificationStorage::GetStringFromResultSet( + std::shared_ptr absSharedResultSet, int columnIndex, std::string &result) +{ + int32_t ret = absSharedResultSet->GetString(columnIndex, result); + if (ret != NativeRdb::E_OK) { + return false; + } + return true; +} + +bool RdbStoreDataCallBackNotificationStorage::WriteBackToDatabase( + NotificationRequest *request, NotificationBundleOption *bundleOption, + NativeRdb::RdbStore &rdbStore, const std::string &tableName) +{ + nlohmann::json jsonOutObject; + if (!NotificationJsonConverter::ConvertToJson(request, jsonOutObject) || + !NotificationJsonConverter::ConvertToJson(bundleOption, jsonOutObject)) { + ANS_LOGE("Convert to json object failed"); + return false; + } + + std::string encryptValue; + AesGcmHelper::Encrypt(jsonOutObject.dump(), encryptValue); + int64_t rowId = -1; + NativeRdb::ValuesBucket valuesBucket; + valuesBucket.PutString(NOTIFICATION_KEY, request->GetSecureKey()); + valuesBucket.PutString(NOTIFICATION_VALUE, encryptValue); + + int32_t ret = rdbStore.InsertWithConflictResolution(rowId, tableName, valuesBucket, + NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE); + if (ret != NativeRdb::E_OK) { + ANS_LOGE("Insert failed with ret: %{public}d", ret); + return false; + } + ANS_LOGI("Insert success ret is %{public}d", ret); + return true; +} + +bool RdbStoreDataCallBackNotificationStorage::UpdateRequest(NotificationRequest *request) +{ + auto actionButtons = request->GetActionButtons(); + if (actionButtons.empty()) { + ANS_LOGE("ActionButtons is empty"); + return false; + } + + auto firstButton = actionButtons.front(); + auto firstButtonWantAgent = firstButton->GetWantAgent(); + auto liveViewContent = std::static_pointer_cast( + request->GetContent()->GetNotificationContent()); + if (firstButtonWantAgent) { + liveViewContent->SetExtensionWantAgent(firstButtonWantAgent); + } + auto requestContent = std::make_shared(liveViewContent); + request->SetContent(requestContent); + + actionButtons.erase(actionButtons.begin()); + request->ClearActionButtons(); + for (auto actionButton : actionButtons) { + request->AddActionButton(actionButton); + } + + ANS_LOGW("End request: %{public}s.", request->Dump().c_str()); + return true; +} int32_t RdbStoreDataCallBackNotificationStorage::OnDowngrade( NativeRdb::RdbStore &rdbStore, int currentVersion, int targetVersion) diff --git a/services/ans/test/unittest/notification_rdb_data_mgr_test/notification_rdb_data_mgr_test.cpp b/services/ans/test/unittest/notification_rdb_data_mgr_test/notification_rdb_data_mgr_test.cpp index b07f6d8c2b94247c3805060451295203843d890e..d9cad6c0bc3e7fd42752f41b194773dcb67a8715 100755 --- a/services/ans/test/unittest/notification_rdb_data_mgr_test/notification_rdb_data_mgr_test.cpp +++ b/services/ans/test/unittest/notification_rdb_data_mgr_test/notification_rdb_data_mgr_test.cpp @@ -367,6 +367,78 @@ HWTEST_F(RdbStoreDataCallBackNotificationStorageTest, RdbStoreDataCallBack_00200 ASSERT_EQ(rdbStoreData_->OnOpen(rdbStore), NativeRdb::E_OK); } +/** + * @tc.name : OnUpgrade_00001 + * @tc.number : + * @tc.desc : test OnUpgrade function when oldVersion is 1 + */ +HWTEST_F(RdbStoreDataCallBackNotificationStorageTest, OnUpgrade_00001, Function | SmallTest | Level1) +{ + NotificationRdbConfig notificationRdbConfig; + std::unique_ptr rdbStoreData_ = + std::make_unique(notificationRdbConfig); + auto rdbStore = std::make_shared(); + int32_t oldVersion = 1; + int32_t newVersion = 2; + // Test OnUpgrade when oldVersion is 1 + ASSERT_EQ(rdbStoreData_->OnUpgrade(*rdbStore, oldVersion, newVersion), NativeRdb::E_OK); +} + +/** + * @tc.name : GetTableNames_00001 + * @tc.number : + * @tc.desc : test GetTableNames + */ +HWTEST_F(RdbStoreDataCallBackNotificationStorageTest, GetTableNames_00001, Function | SmallTest | Level1) +{ + NotificationRdbConfig notificationRdbConfig; + std::unique_ptr rdbStoreData_ = + std::make_unique(notificationRdbConfig); + auto rdbStore = std::make_shared(); + std::shared_ptr absSharedResultSet = + std::make_shared(); + auto result = rdbStoreData_->GetTableNames(*rdbStore); + EXPECT_TRUE(result.empty()); +} + +/** + * @tc.name : ProcessTable_00001 + * @tc.number : + * @tc.desc : test OnUpgrade function when oldVersion is 1 + */ +HWTEST_F(RdbStoreDataCallBackNotificationStorageTest, ProcessTable_00001, Function | SmallTest | Level1) +{ + NotificationRdbConfig notificationRdbConfig; + std::unique_ptr rdbStoreData_ = + std::make_unique(notificationRdbConfig); + auto rdbStore = std::make_shared(); + std::string tableName = "testTable"; + + bool result = rdbStoreData_->ProcessTable(*rdbStore, tableName); + + EXPECT_FALSE(result); +} + +/** + * @tc.name : ProcessTable_00002 + * @tc.number : + * @tc.desc : test OnUpgrade function when oldVersion is 1 + */ +HWTEST_F(RdbStoreDataCallBackNotificationStorageTest, ProcessTable_00002, Function | SmallTest | Level1) +{ + NotificationRdbConfig notificationRdbConfig; + std::unique_ptr rdbStoreData_ = + std::make_unique(notificationRdbConfig); + auto rdbStore = std::make_shared(); + std::string tableName = "testTable"; + + auto mockAbsSharedResultSet = std::make_shared(); + + bool result = rdbStoreData_->ProcessTable(*rdbStore, tableName); + + EXPECT_FALSE(result); +} + /** * @tc.name : RdbStoreDataCallBack_00300 * @tc.number : 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 d295ccfee105d4d7b8bf0b5d27dc39e2e3143353..709416523f7623a1573fc8563b1dc98cc29ae537 100644 --- a/services/distributed/src/soft_bus/distributed_publish_service_v2.cpp +++ b/services/distributed/src/soft_bus/distributed_publish_service_v2.cpp @@ -583,9 +583,8 @@ void DistributedPublishService::SetNotificationButtons(const sptrIsCommonLiveView()) { + if (deviceType == DistributedHardware::DmDeviceType::DEVICE_TYPE_PAD || + deviceType == DistributedHardware::DmDeviceType::DEVICE_TYPE_PC) { std::vector buttonsTitle; size_t length = actionButtons.size(); if (length > NotificationConstant::MAX_BTN_NUM) { @@ -883,7 +882,7 @@ void DistributedPublishService::MakeNotificationButtons(const NotificationReques void DistributedPublishService::MakePadNotificationButtons( const NotificationRequestBox& box, sptr& request) { - if (request == nullptr || request->IsCommonLiveView()) { + if (request == nullptr) { return; } std::vector buttonsTitle;