已开启
优化批量查询接口GetReminderInfoByBundles,改为真实批量查询 #5036
优化批量查询接口GetReminderInfoByBundles,改为真实批量查询 #5036
已开启
luxin创建于 9月9日
共 9 个文件变更+505-45
@@ -1987,6 +1987,9 @@ public:
1987 const sptr<NotificationBundleOption> &bundleOption);1987 const sptr<NotificationBundleOption> &bundleOption);
1988 static std::vector<sptr<NotificationBundleOption>> ResolveBundleOptionUids(1988 static std::vector<sptr<NotificationBundleOption>> ResolveBundleOptionUids(
1989 const std::vector<sptr<NotificationBundleOption>> &bundleOptions);1989 const std::vector<sptr<NotificationBundleOption>> &bundleOptions);
1990+ static void GenerateReminderInfoList(const std::vector<sptr<NotificationBundleOption>> &bundles,
1991+ const std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> &reminderInfos,
1992+ std::vector<NotificationReminderInfo> &reminderInfo);
1990 void UpdateCloneBundleInfoForRingtone(NotificationRingtoneInfo ringtoneInfo, int32_t userId,1993 void UpdateCloneBundleInfoForRingtone(NotificationRingtoneInfo ringtoneInfo, int32_t userId,
1991 const sptr<NotificationBundleOption> bundle, const NotificationCloneBundleInfo cloneBundleInfo);1994 const sptr<NotificationBundleOption> bundle, const NotificationCloneBundleInfo cloneBundleInfo);
1992 1995 
@@ -166,7 +166,20 @@ public:
166 */166 */
167 bool GetShowBadgeEnabledForBundles(const std::vector<sptr<NotificationBundleOption>> &bundleOptions,167 bool GetShowBadgeEnabledForBundles(const std::vector<sptr<NotificationBundleOption>> &bundleOptions,
168 std::map<sptr<NotificationBundleOption>, bool> &bundleEnable, int32_t userId);168 std::map<sptr<NotificationBundleOption>, bool> &bundleEnable, int32_t userId);
169- 169+
170+ /**
171+ * @brief Batch query reminder flags and silent reminder state for multiple bundles.
172+ *
173+ * @param bundleOptions Indicates the bundle options to query.
174+ * @param reminderInfos Indicates the output values, index-aligned with bundleOptions.
175+ * @param userId Indicates the user id for table routing.
176+ * @param flags DEFAULT_SLOT_FLAGS.
177+ * @return Return true on success, false on failure.
178+ */
179+ bool GetReminderInfoForBundles(const std::vector<sptr<NotificationBundleOption>> &bundleOptions,
180+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> &reminderInfos,
181+ int32_t userId, uint32_t defaultSlotFlags);
182+ 
170 /**183 /**
171 * @brief Set show badge in the of bunlde from DB.184 * @brief Set show badge in the of bunlde from DB.
172 *185 *
@@ -455,6 +455,19 @@ public:
455 bool GetShowBadgeEnabledForBundles(const std::vector<sptr<NotificationBundleOption>> &bundleOptions,455 bool GetShowBadgeEnabledForBundles(const std::vector<sptr<NotificationBundleOption>> &bundleOptions,
456 std::map<sptr<NotificationBundleOption>, bool> &bundleEnable, int32_t userId);456 std::map<sptr<NotificationBundleOption>, bool> &bundleEnable, int32_t userId);
457 457 
458+ /**
459+ * @brief Batch query reminder flags and silent reminder state for multiple bundles.
460+ *
461+ * @param bundleOptions Indicates the bundle options to query.
462+ * @param reminderInfos Indicates the output values, index-aligned with bundleOptions.
463+ * @param userId Indicates the user id for table routing.
464+ * @param defaultSlotFlags DEFAULT_SLOT_FLAGS.
465+ * @return Return true on success, false on failure.
466+ */
467+ bool GetReminderInfoForBundles(const std::vector<sptr<NotificationBundleOption>> &bundleOptions,
468+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> &reminderInfos,
469+ int32_t userId, uint32_t defaultSlotFlags);
470+
458 /**471 /**
459 * @brief Delete all slots in the of bundle from disturbe DB.472 * @brief Delete all slots in the of bundle from disturbe DB.
460 *473 *
@@ -149,6 +149,25 @@ ErrCode AdvancedNotificationService::PreReminderInfoCheck()
149 return ERR_OK;149 return ERR_OK;
150}150}
151 151 
152+void AdvancedNotificationService::GenerateReminderInfoList(
153+ const std::vector<sptr<NotificationBundleOption>> &bundles,
154+ const std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> &reminderInfos,
155+ std::vector<NotificationReminderInfo> &reminderInfo)
156+{
157+ for (size_t i = 0; i < bundles.size(); ++i) {
158+ if (bundles[i] == nullptr || i >= reminderInfos.size()) {
159+ continue;
160+ }
161+ NotificationReminderInfo reminder;
162+ reminder.SetBundleOption(*(bundles[i]));
163+ reminder.SetReminderFlags(reminderInfos[i].first);
164+ reminder.SetSilentReminderEnabled(
165+ (reminderInfos[i].second == NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_ON) ||
166+ (reminderInfos[i].second == NotificationConstant::SWITCH_STATE::USER_MODIFIED_ON));
167+ reminderInfo.emplace_back(reminder);
168+ }
169+}
170+ 
152ErrCode AdvancedNotificationService::GetReminderInfoByBundles(171ErrCode AdvancedNotificationService::GetReminderInfoByBundles(
153 const std::vector<sptr<NotificationBundleOption>> &bundles, std::vector<NotificationReminderInfo> &reminderInfo)172 const std::vector<sptr<NotificationBundleOption>> &bundles, std::vector<NotificationReminderInfo> &reminderInfo)
154{173{
@@ -158,58 +177,37 @@ ErrCode AdvancedNotificationService::GetReminderInfoByBundles(
158 return result;177 return result;
159 }178 }
160 HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_26, EventBranchId::BRANCH_3);179 HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_26, EventBranchId::BRANCH_3);
180+ auto resolvedBundles = ResolveBundleOptionUids(bundles);
A
Aafwk_helper9月9日

🤖 AI 代码检视意见(回复本评论可解决检视意见,点击被检视代码行左侧的小头像可收起检视意见)


🟡 线程安全与设计问题:将 Bundle 解析移出任务队列

位置: L161 | 严重程度: Medium

❓ 问题描述

原代码将 GenerateValidBundleOption 调用放在了 notificationSvrQueue_.SyncSubmit 的 lambda 内部,保证了相关操作在专用线程上下文中执行。新代码将 ResolveBundleOptionUids 移到了 SyncSubmit 之外执行,这违背了原有的线程安全设计,可能在调用线程(如 IPC 线程)引发潜在的并发问题或数据竞争。

💡 修复建议

修改建议:将 ResolveBundleOptionUids 及相关变量的初始化移入 notificationSvrQueue_.SyncSubmit 的 lambda 内部,保持与原设计一致的线程模型。

159: HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_26, EventBranchId::BRANCH_3); 160: result = ERR_OK; 161: auto submitResult = notificationSvrQueue_.SyncSubmit(std::bind(& { 162: ANS_LOGD("ffrt enter!"); 163: auto resolvedBundles = ResolveBundleOptionUids(bundles); 164: int32_t userId = -1; 165: if (OsAccountManagerHelper::GetInstance().GetCurrentCallingUserId(userId) != ERR_OK) {


likedislike
181+ int32_t userId = -1;
182+ if (OsAccountManagerHelper::GetInstance().GetCurrentCallingUserId(userId) != ERR_OK) {
183+ ANS_LOGW("GetCurrentCallingUserId failed, query shared table only.");
184+ }
185+ uint32_t flags = DEFAULT_SLOT_FLAGS;
186+ result = ERR_OK;
161 auto submitResult = notificationSvrQueue_.SyncSubmit(std::bind([&]() {187 auto submitResult = notificationSvrQueue_.SyncSubmit(std::bind([&]() {
162 ANS_LOGD("ffrt enter!");188 ANS_LOGD("ffrt enter!");
163- for (const auto &bundle : bundles) {189+ if (resolvedBundles.empty()) {
164- uint32_t flags = DEFAULT_SLOT_FLAGS;190+ ANS_LOGD("No valid bundle options after uid resolution.");
165- NotificationConstant::SWITCH_STATE enableStatus;191+ return;
166- bool silentReminderEnabled = false;
167- NotificationReminderInfo reminder;
168- // 1、GenerateValidBundleOption
169- sptr<NotificationBundleOption> validBundle = GenerateValidBundleOption(bundle);
170- if (validBundle == nullptr) {
171- continue;
172- }
173- 
174- // 2、GetNotificationSlotFlagsForBundle
175- result = NotificationPreferences::GetInstance()->GetNotificationSlotFlagsForBundle(validBundle, flags);
176- if (result == ERR_ANS_INNER_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
177- result = ERR_OK;
178- flags = DEFAULT_SLOT_FLAGS;
179- }
180- if (result != ERR_OK) {
181- ANS_LOGE("%{public}s_%{public}d, get reminderflags failed.",
182- validBundle->GetBundleName().c_str(), validBundle->GetUid());
183- message.Message(validBundle->GetBundleName() + "_" + std::to_string(validBundle->GetUid()) +
184- " get reminderflags failed.");
185- NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(result));
186- continue;
187- }
188- 
189- //3、IsSilentReminderEnabled
190- result = NotificationPreferences::GetInstance()->IsSilentReminderEnabled(validBundle, enableStatus);
191- silentReminderEnabled = ((enableStatus == NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_ON) ||
192- (enableStatus == NotificationConstant::SWITCH_STATE::USER_MODIFIED_ON));
193- if (result != ERR_OK) {
194- ANS_LOGE("%{public}s_%{public}d, get silentreminderenable failed.",
195- validBundle->GetBundleName().c_str(), validBundle->GetUid());
196- message.Message(validBundle->GetBundleName() + "_" + std::to_string(validBundle->GetUid()) +
197- " get silentreminderenable failed.");
198- NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(result).BranchId(BRANCH_4));
199- continue;
200- }
201- reminder.SetBundleOption(*validBundle);
202- reminder.SetReminderFlags(flags);
203- reminder.SetSilentReminderEnabled(silentReminderEnabled);
204- reminderInfo.emplace_back(reminder);
205 }192 }
193+ 
194+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> reminderInfos;
195+ if (!NotificationPreferences::GetInstance()->GetReminderInfoForBundles(
196+ resolvedBundles, reminderInfos, userId, flags)) {
197+ result = ERR_ANS_INNER_PREFERENCES_NOTIFICATION_DB_OPERATION_FAILED;
198+ message.Message(std::to_string(resolvedBundles.size()) + " bundles get reminder info failed.");
199+ NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(result).BranchId(BRANCH_4));
200+ return;
201+ }
202+ 
203+ GenerateReminderInfoList(resolvedBundles, reminderInfos, reminderInfo);
206 }));204 }));
207 205 
208 ANS_COND_DO_ERR(submitResult != ERR_OK, return submitResult, "Get reminder info by bundles.");206 ANS_COND_DO_ERR(submitResult != ERR_OK, return submitResult, "Get reminder info by bundles.");
209 ANS_LOGI("GetReminderInfoByBundles end");207 ANS_LOGI("GetReminderInfoByBundles end");
210 NotificationAnalyticsUtil::ReportModifyEvent(208 NotificationAnalyticsUtil::ReportModifyEvent(
211 message.ErrorCode(result).Message("GetReminderInfoByBundles end.").BranchId(BRANCH_5));209 message.ErrorCode(result).Message("GetReminderInfoByBundles end.").BranchId(BRANCH_5));
212- return ERR_OK;210+ return result;
213}211}
214 212 
215ErrCode AdvancedNotificationService::SetReminderInfoByBundles(213ErrCode AdvancedNotificationService::SetReminderInfoByBundles(
@@ -1341,6 +1341,19 @@ bool __attribute__((weak)) NotificationPreferences::GetShowBadgeEnabledForBundle
1341 return preferncesDB_->GetShowBadgeEnabledForBundles(bundleOptions, bundleEnable, userId);1341 return preferncesDB_->GetShowBadgeEnabledForBundles(bundleOptions, bundleEnable, userId);
1342}1342}
1343 1343 
1344+bool __attribute__((weak)) NotificationPreferences::GetReminderInfoForBundles(
1345+ const std::vector<sptr<NotificationBundleOption>> &bundleOptions,
1346+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> &reminderInfos,
1347+ int32_t userId, uint32_t defaultSlotFlags)
1348+{
1349+ ANS_LOGD("called");
1350+ std::lock_guard<ffrt::mutex> lock(preferenceMutex_);
1351+ if (preferncesDB_ == nullptr) {
1352+ return false;
1353+ }
1354+ return preferncesDB_->GetReminderInfoForBundles(bundleOptions, reminderInfos, userId, defaultSlotFlags);
1355+}
1356+ 
1344ErrCode NotificationPreferences::ClearNotificationInRestoreFactorySettings()1357ErrCode NotificationPreferences::ClearNotificationInRestoreFactorySettings()
1345{1358{
1346 ErrCode result = ERR_OK;1359 ErrCode result = ERR_OK;
@@ -291,6 +291,12 @@ constexpr int32_t SILENT_REMINDER_DISABLED = 0;
291 */291 */
292constexpr int32_t SILENT_REMINDER_ENABLED = 1;292constexpr int32_t SILENT_REMINDER_ENABLED = 1;
293 293 
294+/**
295+ * Indicates that each bundle contributes two reminder query keys:
296+ * slot flags and silent reminder state.
297+ */
298+constexpr size_t REMINDER_KEYS_PER_BUNDLE = 2;
299+ 
294/**300/**
295 * Indicates that bundle has not popped dialog stored in disturbe DB.301 * Indicates that bundle has not popped dialog stored in disturbe DB.
296 */302 */
@@ -1267,6 +1273,62 @@ bool NotificationPreferencesDatabase::GetShowBadgeEnabledForBundles(
1267 return true;1273 return true;
1268}1274}
1269 1275 
1276+bool NotificationPreferencesDatabase::GetReminderInfoForBundles(
1277+ const std::vector<sptr<NotificationBundleOption>> &bundleOptions,
1278+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> &reminderInfos,
1279+ int32_t userId, uint32_t defaultSlotFlags)
1280+{
1281+ ANS_LOGD("called");
1282+ if (!CheckRdbStore()) {
1283+ return false;
1284+ }
1285+ if (bundleOptions.empty()) {
1286+ return false;
1287+ }
1288+ 
1289+ std::vector<std::string> keys;
1290+ keys.reserve(bundleOptions.size() * REMINDER_KEYS_PER_BUNDLE);
1291+ for (const auto &bundleOption : bundleOptions) {
1292+ if (bundleOption == nullptr) {
1293+ continue;
1294+ }
1295+ std::string bundleKey = bundleOption->GetBundleName() + std::to_string(bundleOption->GetUid());
1296+ keys.push_back(GenerateBundleKey(bundleKey, KEY_BUNDLE_SLOTFLGS_TYPE));
1297+ keys.push_back(GenerateBundleKey(bundleKey, KEY_SILENT_REMINDER_ENABLE_NOTIFICATION));
1298+ }
1299+ if (keys.empty()) {
1300+ return true;
1301+ }
1302+ 
1303+ std::unordered_map<std::string, std::string> results;
1304+ if (rdbDataManager_->QueryDataInKeys(keys, results, userId) != NativeRdb::E_OK) {
1305+ ANS_LOGE("Query reminder info for bundles failed.");
1306+ return false;
1307+ }
1308+ reminderInfos.clear();
1309+ reminderInfos.reserve(bundleOptions.size());
1310+ for (const auto &bundleOption : bundleOptions) {
A
Aafwk_helper9月9日

🤖 AI 代码检视意见(回复本评论可解决检视意见,点击被检视代码行左侧的小头像可收起检视意见)


🟠 空指针处理逻辑不一致导致索引对齐风险

位置: L1304-L1321 | 严重程度: High

❓ 问题描述

在 GetReminderInfoForBundles 的第一个循环中,遇到 nullptr 会跳过生成键;但在第二个循环中,遇到 nullptr 却不跳过,而是直接插入默认值。这种处理逻辑使得 reminderInfos 的索引与 bundleOptions 强对齐,但在上层调用者 advanced_notification_reminder_service.cpp 中直接解引用 resolvedBundles[i] 会导致空指针崩溃。此设计非常脆弱且与测试用例的期望存在矛盾。

💡 修复建议

修改建议:统一空指针处理策略。若决定在输入端过滤空指针,则在数据库层不应保留空位对齐逻辑,同时上层调用者需保证不传入空指针;并修正测试用例中相互矛盾的期望。

1304: for (const auto &bundleOption : bundleOptions) { 1305: if (bundleOption == nullptr) { 1306: continue; 1307: } 1308: uint32_t slotFlags = defaultSlotFlags; 1309: NotificationConstant::SWITCH_STATE silentState = NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_OFF; 1310: std::string bundleKey = bundleOption->GetBundleName() + std::to_string(bundleOption->GetUid()); 1311: auto slotFlagsIter = results.find(GenerateBundleKey(bundleKey, KEY_BUNDLE_SLOTFLGS_TYPE)); 1312: if (slotFlagsIter != results.end()) { 1313: slotFlags = static_cast<uint32_t>(AnsCommonUtils::StringToInt(slotFlagsIter->second)); 1314: } 1315: auto silentIter = results.find(GenerateBundleKey(bundleKey, KEY_SILENT_REMINDER_ENABLE_NOTIFICATION)); 1316: if (silentIter != results.end()) { 1317: silentState = AnsCommonUtils::StringToInt(silentIter->second) ? 1318: NotificationConstant::SWITCH_STATE::USER_MODIFIED_ON : 1319: NotificationConstant::SWITCH_STATE::USER_MODIFIED_OFF; 1320: } 1321: reminderInfos.emplace_back(slotFlags, silentState); 1322: }


likedislike
luxin
luxin
9月10日 评论:
1311+ if (bundleOption == nullptr) {
1312+ continue;
1313+ }
1314+ uint32_t slotFlags = defaultSlotFlags;
1315+ NotificationConstant::SWITCH_STATE silentState = NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_OFF;
1316+ std::string bundleKey = bundleOption->GetBundleName() + std::to_string(bundleOption->GetUid());
1317+ auto slotFlagsIter = results.find(GenerateBundleKey(bundleKey, KEY_BUNDLE_SLOTFLGS_TYPE));
1318+ if (slotFlagsIter != results.end()) {
1319+ slotFlags = static_cast<uint32_t>(AnsCommonUtils::StringToInt(slotFlagsIter->second));
1320+ }
1321+ auto silentIter = results.find(GenerateBundleKey(bundleKey, KEY_SILENT_REMINDER_ENABLE_NOTIFICATION));
1322+ if (silentIter != results.end()) {
1323+ silentState = AnsCommonUtils::StringToInt(silentIter->second) ?
1324+ NotificationConstant::SWITCH_STATE::USER_MODIFIED_ON :
1325+ NotificationConstant::SWITCH_STATE::USER_MODIFIED_OFF;
1326+ }
1327+ reminderInfos.emplace_back(slotFlags, silentState);
1328+ }
1329+ return true;
1330+}
1331+ 
1270bool NotificationPreferencesDatabase::HandleDataBaseMapInner(1332bool NotificationPreferencesDatabase::HandleDataBaseMapInner(
1271 const std::unordered_map<std::string, std::string> &datas,1333 const std::unordered_map<std::string, std::string> &datas,
1272 std::vector<NotificationBundleOption> &bundleOption, const int32_t currentUserId)1334 std::vector<NotificationBundleOption> &bundleOption, const int32_t currentUserId)
@@ -1336,6 +1336,168 @@ HWTEST_F(AnsSlotServiceTest, GetReminderInfoByBundles_0400, Function | SmallTest
1336 ASSERT_EQ(ret, (int)ERR_OK);1336 ASSERT_EQ(ret, (int)ERR_OK);
1337}1337}
1338 1338 
1339+/**
1340+ * @tc.name: GetReminderInfoByBundles_0500
1341+ * @tc.desc: Test batch query returns stored values, defaults for missing keys, in input order
1342+ * @tc.type: FUNC
1343+ * @tc.require: issue
1344+ */
1345+HWTEST_F(AnsSlotServiceTest, GetReminderInfoByBundles_0500, Function | SmallTest | Level1)
1346+{
1347+ MockGetTokenTypeFlag(Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE);
1348+ MockIsSystemApp(true);
1349+ MockIsVerfyPermisson(true);
1350+ MockGetOsAccountLocalIdFromUid(true, 0);
1351+ 
1352+ const std::string storedName = "ReminderStoredBundle_0500";
1353+ const int32_t storedUid = 10001;
1354+ const uint32_t storedFlags = 40; // 0b101000
1355+ std::string bundleKey = storedName + std::to_string(storedUid);
1356+ NotificationPreferences::GetInstance()->SetKvToDb(
1357+ "ans_bundle_" + bundleKey + "_bundleReminderFlagsType", std::to_string(storedFlags), 100);
1358+ NotificationPreferences::GetInstance()->SetKvToDb(
1359+ "ans_bundle_" + bundleKey + "_enabledSilentReminder", "1", 100);
1360+ 
1361+ std::vector<sptr<NotificationBundleOption>> bundles;
1362+ bundles.emplace_back(new NotificationBundleOption(storedName, storedUid));
1363+ bundles.emplace_back(new NotificationBundleOption("ReminderMissingBundle_0500", 10002));
1364+ std::vector<NotificationReminderInfo> reminders;
1365+ auto ret = advancedNotificationService_->GetReminderInfoByBundles(bundles, reminders);
1366+ ASSERT_EQ(ret, (int)ERR_OK);
1367+ ASSERT_EQ(2u, reminders.size());
1368+ // index-aligned: output order follows input order
1369+ EXPECT_EQ(storedName, reminders[0].GetBundleOption().GetBundleName());
1370+ EXPECT_EQ(storedFlags, reminders[0].GetReminderFlags());
1371+ EXPECT_TRUE(reminders[0].GetSilentReminderEnabled());
1372+ EXPECT_EQ(DEFAULT_SLOT_FLAGS, reminders[1].GetReminderFlags());
1373+ EXPECT_FALSE(reminders[1].GetSilentReminderEnabled());
1374+}
1375+ 
1376+/**
1377+ * @tc.name: GetReminderInfoByBundles_0600
1378+ * @tc.desc: Test empty bundles input returns ERR_OK with empty output
1379+ * @tc.type: FUNC
1380+ * @tc.require: issue
1381+ */
1382+HWTEST_F(AnsSlotServiceTest, GetReminderInfoByBundles_0600, Function | SmallTest | Level1)
1383+{
1384+ MockGetTokenTypeFlag(Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE);
1385+ MockIsSystemApp(true);
1386+ MockIsVerfyPermisson(true);
1387+ MockGetOsAccountLocalIdFromUid(true, 0);
1388+ 
1389+ std::vector<sptr<NotificationBundleOption>> bundles;
1390+ std::vector<NotificationReminderInfo> reminders;
1391+ auto ret = advancedNotificationService_->GetReminderInfoByBundles(bundles, reminders);
1392+ ASSERT_EQ(ret, (int)ERR_OK);
1393+ ASSERT_EQ(0u, reminders.size());
1394+}
1395+ 
1396+/**
1397+ * @tc.name: GetReminderInfoByBundles_0700
1398+ * @tc.desc: Test batch query failure (null preferences db)
1399+ * @tc.type: FUNC
1400+ * @tc.require: issue
1401+ */
1402+HWTEST_F(AnsSlotServiceTest, GetReminderInfoByBundles_0700, Function | SmallTest | Level1)
1403+{
1404+ MockGetTokenTypeFlag(Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE);
1405+ MockIsSystemApp(true);
1406+ MockIsVerfyPermisson(true);
1407+ MockGetOsAccountLocalIdFromUid(true, 0);
1408+ 
1409+ auto preferences = NotificationPreferences::GetInstance();
1410+ auto originalDB = preferences->preferncesDB_;
1411+ preferences->preferncesDB_ = nullptr;
1412+ std::vector<sptr<NotificationBundleOption>> bundles;
1413+ bundles.emplace_back(new NotificationBundleOption("ReminderNullDB_0700", 10001));
1414+ std::vector<NotificationReminderInfo> reminders;
1415+ auto ret = advancedNotificationService_->GetReminderInfoByBundles(bundles, reminders);
1416+ preferences->preferncesDB_ = originalDB;
1417+ ASSERT_EQ(ret, (int)ERR_ANS_INNER_PREFERENCES_NOTIFICATION_DB_OPERATION_FAILED);
1418+ ASSERT_EQ(0u, reminders.size());
1419+}
1420+ 
1421+/**
1422+ * @tc.name: GetReminderInfoByBundles_0800
1423+ * @tc.desc: Test GetCurrentCallingUserId failure falls back to shared table with defaults
1424+ * @tc.type: FUNC
1425+ * @tc.require: issue
1426+ */
1427+HWTEST_F(AnsSlotServiceTest, GetReminderInfoByBundles_0800, Function | SmallTest | Level1)
1428+{
1429+ MockGetTokenTypeFlag(Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE);
1430+ MockIsSystemApp(true);
1431+ MockIsVerfyPermisson(true);
1432+ MockGetOsAccountLocalIdFromUid(false, 1); // GetCurrentCallingUserId fails (uid -> userId fails)
1433+ 
1434+ std::vector<sptr<NotificationBundleOption>> bundles;
1435+ bundles.emplace_back(new NotificationBundleOption("ReminderUserFail_0800", 10001));
1436+ std::vector<NotificationReminderInfo> reminders;
1437+ auto ret = advancedNotificationService_->GetReminderInfoByBundles(bundles, reminders);
1438+ MockGetOsAccountLocalIdFromUid(true, 0); // reset to default for subsequent tests
1439+ ASSERT_EQ(ret, (int)ERR_OK);
1440+ ASSERT_EQ(1u, reminders.size());
1441+ EXPECT_EQ(DEFAULT_SLOT_FLAGS, reminders[0].GetReminderFlags());
1442+ EXPECT_FALSE(reminders[0].GetSilentReminderEnabled());
1443+}
1444+ 
1445+/**
1446+ * @tc.name: GetReminderInfoByBundles_0900
1447+ * @tc.desc: Test GenerateReminderInfoList skips null bundle entries
1448+ * @tc.type: FUNC
1449+ * @tc.require: issue
1450+ */
1451+HWTEST_F(AnsSlotServiceTest, GetReminderInfoByBundles_0900, Function | SmallTest | Level1)
1452+{
1453+ std::vector<sptr<NotificationBundleOption>> bundles;
1454+ bundles.emplace_back(nullptr);
1455+ bundles.emplace_back(new NotificationBundleOption("ReminderNullEntry_0900", 10001));
1456+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> reminderInfos = {
1457+ {59, NotificationConstant::SWITCH_STATE::USER_MODIFIED_ON},
1458+ {40, NotificationConstant::SWITCH_STATE::USER_MODIFIED_ON}};
1459+ std::vector<NotificationReminderInfo> reminders;
1460+ AdvancedNotificationService::GenerateReminderInfoList(bundles, reminderInfos, reminders);
1461+ ASSERT_EQ(1u, reminders.size());
1462+ EXPECT_EQ("ReminderNullEntry_0900", reminders[0].GetBundleOption().GetBundleName());
1463+ EXPECT_EQ(40u, reminders[0].GetReminderFlags());
1464+ EXPECT_TRUE(reminders[0].GetSilentReminderEnabled());
1465+}
1466+ 
1467+/**
1468+ * @tc.name: GetReminderInfoByBundles_1000
1469+ * @tc.desc: Test GenerateReminderInfoList outputs nothing when reminderInfos is shorter than bundles
1470+ * @tc.type: FUNC
1471+ * @tc.require: issue
1472+ */
1473+HWTEST_F(AnsSlotServiceTest, GetReminderInfoByBundles_1000, Function | SmallTest | Level1)
1474+{
1475+ std::vector<sptr<NotificationBundleOption>> bundles;
1476+ bundles.emplace_back(new NotificationBundleOption("ReminderShortList_1000", 10001));
1477+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> reminderInfos;
1478+ std::vector<NotificationReminderInfo> reminders;
1479+ AdvancedNotificationService::GenerateReminderInfoList(bundles, reminderInfos, reminders);
1480+ ASSERT_EQ(0u, reminders.size());
1481+}
1482+ 
1483+/**
1484+ * @tc.name: GetReminderInfoByBundles_1100
1485+ * @tc.desc: Test GenerateReminderInfoList treats SYSTEM_DEFAULT_ON as silent enabled
1486+ * @tc.type: FUNC
1487+ * @tc.require: issue
1488+ */
1489+HWTEST_F(AnsSlotServiceTest, GetReminderInfoByBundles_1100, Function | SmallTest | Level1)
1490+{
1491+ std::vector<sptr<NotificationBundleOption>> bundles;
1492+ bundles.emplace_back(new NotificationBundleOption("ReminderDefaultOn_1100", 10001));
1493+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> reminderInfos = {
1494+ {59, NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_ON}};
1495+ std::vector<NotificationReminderInfo> reminders;
1496+ AdvancedNotificationService::GenerateReminderInfoList(bundles, reminderInfos, reminders);
1497+ ASSERT_EQ(1u, reminders.size());
1498+ EXPECT_TRUE(reminders[0].GetSilentReminderEnabled());
1499+}
1500+ 
1339/**1501/**
1340 * @tc.name: UpdateInnerConfig_000011502 * @tc.name: UpdateInnerConfig_00001
1341 * @tc.desc: Test UpdateInnerConfig permission and param check1503 * @tc.desc: Test UpdateInnerConfig permission and param check
@@ -15,11 +15,14 @@
15 15 
16#define private public16#define private public
17#include <gtest/gtest.h>17#include <gtest/gtest.h>
18+#include <sys/types.h>
19+#include <unistd.h>
18 20 
19#define private public21#define private public
20#define protected public22#define protected public
21#include "notification_preferences_database.h"23#include "notification_preferences_database.h"
22#include "notification_preferences.h"24#include "notification_preferences.h"
25+#include "notification_rdb_mgr.h"
23#include "rdb_errno.h"26#include "rdb_errno.h"
24#undef private27#undef private
25#undef protected28#undef protected
@@ -4789,5 +4792,141 @@ HWTEST_F(NotificationPreferencesDatabaseTest, RemoveSlotFromDisturbeDB_00300, Fu
4789 MockOsAccountManager::MockGetOsAccountLocalIdFromUid(100); // reset to default for subsequent tests4792 MockOsAccountManager::MockGetOsAccountLocalIdFromUid(100); // reset to default for subsequent tests
4790}4793}
4791 4794 
4795+/**
4796+ * @tc.name : GetReminderInfoForBundles_00100
4797+ * @tc.number : GetReminderInfoForBundles_00100
4798+ * @tc.desc : Test GetReminderInfoForBundles with empty bundleOptions, return false.
4799+ */
4800+HWTEST_F(NotificationPreferencesDatabaseTest, GetReminderInfoForBundles_00100, Function | SmallTest | Level1)
4801+{
4802+ std::vector<sptr<NotificationBundleOption>> bundleOptions;
4803+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> reminderInfos;
4804+ EXPECT_FALSE(preferncesDB_->GetReminderInfoForBundles(bundleOptions, reminderInfos, 0, 59));
4805+ EXPECT_EQ(0u, reminderInfos.size());
4806+}
4807+ 
4808+/**
4809+ * @tc.name : GetReminderInfoForBundles_00200
4810+ * @tc.number : GetReminderInfoForBundles_00200
4811+ * @tc.desc : Test GetReminderInfoForBundles with null bundle option only, returns true with empty output.
4812+ */
4813+HWTEST_F(NotificationPreferencesDatabaseTest, GetReminderInfoForBundles_00200, Function | SmallTest | Level1)
4814+{
4815+ std::vector<sptr<NotificationBundleOption>> bundleOptions;
4816+ bundleOptions.push_back(nullptr);
4817+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> reminderInfos;
4818+ EXPECT_TRUE(preferncesDB_->GetReminderInfoForBundles(bundleOptions, reminderInfos, 0, 59));
4819+ EXPECT_EQ(0u, reminderInfos.size());
4820+}
4821+ 
4822+/**
4823+ * @tc.name : GetReminderInfoForBundles_00300
4824+ * @tc.number : GetReminderInfoForBundles_00300
4825+ * @tc.desc : Test GetReminderInfoForBundles with null rdbDataManager, return false.
4826+ */
4827+HWTEST_F(NotificationPreferencesDatabaseTest, GetReminderInfoForBundles_00300, Function | SmallTest | Level1)
4828+{
4829+ preferncesDB_->rdbDataManager_ = nullptr;
4830+ std::vector<sptr<NotificationBundleOption>> bundleOptions;
4831+ bundleOptions.push_back(new NotificationBundleOption("ReminderNullRdb", 1001));
4832+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> reminderInfos;
4833+ EXPECT_FALSE(preferncesDB_->GetReminderInfoForBundles(bundleOptions, reminderInfos, 0, 59));
4834+ EXPECT_EQ(0u, reminderInfos.size());
4835+}
4836+ 
4837+/**
4838+ * @tc.name : GetReminderInfoForBundles_00400
4839+ * @tc.number : GetReminderInfoForBundles_00400
4840+ * @tc.desc : Test end-to-end: stored values are parsed (flags + silent on/off) and missing
4841+ * keys keep the defaults (0b111011 / SYSTEM_DEFAULT_OFF).
4842+ */
4843+HWTEST_F(NotificationPreferencesDatabaseTest, GetReminderInfoForBundles_00400, Function | SmallTest | Level1)
4844+{
4845+ const std::string bundleNameStored = "reminderStoredBundle";
4846+ const int32_t bundleUidStored = 1001;
4847+ const std::string bundleNameOff = "reminderOffBundle";
4848+ const int32_t bundleUidOff = 1002;
4849+ const std::string bundleNameMissing = "reminderMissingBundle";
4850+ const int32_t bundleUidMissing = 1003;
4851+ const int32_t userId = 0;
4852+ const uint32_t storedSlotFlags = 40; // 0b101000
4853+ 
4854+ std::string bundleKeyStored = bundleNameStored + std::to_string(bundleUidStored);
4855+ EXPECT_EQ(NativeRdb::E_OK, preferncesDB_->SetKvToDb(
4856+ preferncesDB_->GenerateBundleKey(bundleKeyStored, "bundleReminderFlagsType"),
4857+ std::to_string(storedSlotFlags), userId));
4858+ EXPECT_EQ(NativeRdb::E_OK, preferncesDB_->SetKvToDb(
4859+ preferncesDB_->GenerateBundleKey(bundleKeyStored, "enabledSilentReminder"), "1", userId));
4860+ std::string bundleKeyOff = bundleNameOff + std::to_string(bundleUidOff);
4861+ EXPECT_EQ(NativeRdb::E_OK, preferncesDB_->SetKvToDb(
4862+ preferncesDB_->GenerateBundleKey(bundleKeyOff, "enabledSilentReminder"), "0", userId));
4863+ 
4864+ std::vector<sptr<NotificationBundleOption>> bundleOptions;
4865+ bundleOptions.push_back(new NotificationBundleOption(bundleNameStored, bundleUidStored));
4866+ bundleOptions.push_back(new NotificationBundleOption(bundleNameOff, bundleUidOff));
4867+ bundleOptions.push_back(new NotificationBundleOption(bundleNameMissing, bundleUidMissing));
4868+ 
4869+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> reminderInfos;
4870+ EXPECT_TRUE(preferncesDB_->GetReminderInfoForBundles(bundleOptions, reminderInfos, userId, 59));
4871+ ASSERT_EQ(3u, reminderInfos.size());
4872+ EXPECT_EQ(storedSlotFlags, reminderInfos[0].first);
4873+ EXPECT_EQ(NotificationConstant::SWITCH_STATE::USER_MODIFIED_ON, reminderInfos[0].second);
4874+ EXPECT_EQ(59u, reminderInfos[1].first);
4875+ EXPECT_EQ(NotificationConstant::SWITCH_STATE::USER_MODIFIED_OFF, reminderInfos[1].second);
4876+ EXPECT_EQ(59u, reminderInfos[2].first);
4877+ EXPECT_EQ(NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_OFF, reminderInfos[2].second);
4878+}
4879+ 
4880+/**
4881+ * @tc.name : GetReminderInfoForBundles_00500
4882+ * @tc.number : GetReminderInfoForBundles_00500
4883+ * @tc.desc : Test mixed [valid, nullptr] input: null entry is skipped and only non-null
4884+ * bundles are present in the output.
4885+ */
4886+HWTEST_F(NotificationPreferencesDatabaseTest, GetReminderInfoForBundles_00500, Function | SmallTest | Level1)
4887+{
4888+ std::vector<sptr<NotificationBundleOption>> bundleOptions;
4889+ bundleOptions.push_back(new NotificationBundleOption("reminderMixedBundle", 1001));
4890+ bundleOptions.push_back(nullptr);
4891+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> reminderInfos;
4892+ EXPECT_TRUE(preferncesDB_->GetReminderInfoForBundles(bundleOptions, reminderInfos, 0, 59));
4893+ ASSERT_EQ(1u, reminderInfos.size());
4894+ EXPECT_EQ(59u, reminderInfos[0].first);
4895+ EXPECT_EQ(NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_OFF, reminderInfos[0].second);
4896+}
4897+ 
4898+/**
4899+ * @tc.name : GetReminderInfoForBundles_00600
4900+ * @tc.number : GetReminderInfoForBundles_00600
4901+ * @tc.desc : Test the QueryDataInKeys failure branch: when the rdb manager is in recovery
4902+ * state, queries short-circuit with E_ERROR and the batch query returns false
4903+ * with the output parameter left untouched.
4904+ */
4905+HWTEST_F(NotificationPreferencesDatabaseTest, GetReminderInfoForBundles_00600, Function | SmallTest | Level1)
4906+{
4907+ auto originalMgr = preferncesDB_->rdbDataManager_;
4908+ Infra::NotificationRdbConfig config;
4909+ config.dbPath = "/data/local/tmp/";
4910+ config.dbName = "notificationdb_recover_test_" + std::to_string(static_cast<int32_t>(getpid())) + ".db";
4911+ const Infra::NtfRdbHook hooks;
4912+ const std::set<Infra::RdbEventHandlerType> eventHandlerTypes = {
4913+ Infra::RdbEventHandlerType::ON_CREATE_INIT_DEFAULT_TABLE,
4914+ };
4915+ auto recoveringMgr = std::make_shared<Infra::NotificationRdbMgr>(config, hooks, eventHandlerTypes);
4916+ ASSERT_NE(nullptr, recoveringMgr);
4917+ ASSERT_EQ(NativeRdb::E_OK, recoveringMgr->Init());
4918+ recoveringMgr->rdbStoreWrapper_->isRecovering_.store(true);
4919+ preferncesDB_->rdbDataManager_ = recoveringMgr;
4920+ std::vector<sptr<NotificationBundleOption>> bundleOptions;
4921+ bundleOptions.push_back(new NotificationBundleOption("reminderQueryFailBundle", 1001));
4922+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> reminderInfos;
4923+ reminderInfos.emplace_back(0, NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_OFF);
4924+ EXPECT_FALSE(preferncesDB_->GetReminderInfoForBundles(bundleOptions, reminderInfos, 0, 59));
4925+ EXPECT_EQ(1u, reminderInfos.size());
4926+ recoveringMgr->rdbStoreWrapper_->isRecovering_.store(false);
4927+ preferncesDB_->rdbDataManager_ = originalMgr;
4928+ recoveringMgr->Destroy();
4929+}
4930+ 
4792} // namespace Notification4931} // namespace Notification
4793} // namespace OHOS4932} // namespace OHOS
@@ -658,7 +658,7 @@ HWTEST_F(NotificationPreferencesTest, GetShowBadgeEnabledForBundles_00300, Funct
658 bundleOptions, bundleEnable, 100));658 bundleOptions, bundleEnable, 100));
659 EXPECT_EQ(1u, bundleEnable.size());659 EXPECT_EQ(1u, bundleEnable.size());
660 EXPECT_NE(bundleEnable.end(), bundleEnable.find(bundleOption_));660 EXPECT_NE(bundleEnable.end(), bundleEnable.find(bundleOption_));
661- EXPECT_FALSE(bundleEnable[bundleOption_]);661+ EXPECT_FALSE(bundleEnable.at(bundleOption_));
662}662}
663 663 
664/**664/**
@@ -5203,5 +5203,62 @@ HWTEST_F(NotificationPreferencesTest, SetDistributedDevicelist_Success_0001, Fun
5203 auto ret = prefs->SetDistributedDevicelist(deviceTypes, 100);5203 auto ret = prefs->SetDistributedDevicelist(deviceTypes, 100);
5204 EXPECT_EQ(ret, ERR_OK); // line 2864-2865 store succeeds5204 EXPECT_EQ(ret, ERR_OK); // line 2864-2865 store succeeds
5205}5205}
5206+ 
5207+/**
5208+ * @tc.number : GetReminderInfoForBundles_00100
5209+ * @tc.name : GetReminderInfoForBundles_00100
5210+ * @tc.desc : Test GetReminderInfoForBundles when preferncesDB_ is null, return false.
5211+ */
5212+HWTEST_F(NotificationPreferencesTest, GetReminderInfoForBundles_00100, Function | SmallTest | Level1)
5213+{
5214+ NotificationPreferences notificationPreferences;
5215+ notificationPreferences.preferncesDB_ = nullptr;
5216+ std::vector<sptr<NotificationBundleOption>> bundleOptions;
5217+ bundleOptions.push_back(bundleOption_);
5218+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> reminderInfos;
5219+ EXPECT_FALSE(notificationPreferences.GetReminderInfoForBundles(bundleOptions, reminderInfos, 100, 59));
5220+ EXPECT_EQ(0u, reminderInfos.size());
5221+}
5222+ 
5223+/**
5224+ * @tc.number : GetReminderInfoForBundles_00200
5225+ * @tc.name : GetReminderInfoForBundles_00200
5226+ * @tc.desc : Test GetReminderInfoForBundles when rdb data manager is null, return false.
5227+ */
5228+HWTEST_F(NotificationPreferencesTest, GetReminderInfoForBundles_00200, Function | SmallTest | Level1)
5229+{
5230+ NotificationPreferences notificationPreferences;
5231+ notificationPreferences.preferncesDB_ = std::make_shared<NotificationPreferencesDatabase>();
5232+ notificationPreferences.preferncesDB_->rdbDataManager_ = nullptr;
5233+ std::vector<sptr<NotificationBundleOption>> bundleOptions;
5234+ bundleOptions.push_back(bundleOption_);
5235+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> reminderInfos;
5236+ EXPECT_FALSE(notificationPreferences.GetReminderInfoForBundles(bundleOptions, reminderInfos, 100, 59));
5237+ EXPECT_EQ(0u, reminderInfos.size());
5238+}
5239+ 
5240+/**
5241+ * @tc.number : GetReminderInfoForBundles_00300
5242+ * @tc.name : GetReminderInfoForBundles_00300
5243+ * @tc.desc : Set reminder flags and silent reminder for bundle, then batch query
5244+ * returns the persisted values.
5245+ */
5246+HWTEST_F(NotificationPreferencesTest, GetReminderInfoForBundles_00300, Function | SmallTest | Level1)
5247+{
5248+ MockGetOsAccountLocalIdFromUid(true);
5249+ sptr<NotificationBundleOption> bundle = new NotificationBundleOption("ReminderInfoBundle", 2001);
5250+ EXPECT_EQ((int)NotificationPreferences::GetInstance()->SetNotificationSlotFlagsForBundle(bundle, 40),
5251+ (int)ERR_OK);
5252+ EXPECT_EQ((int)NotificationPreferences::GetInstance()->SetSilentReminderEnabled(bundle, true), (int)ERR_OK);
5253+ std::vector<sptr<NotificationBundleOption>> bundleOptions;
5254+ bundleOptions.push_back(bundle);
5255+ std::vector<std::pair<uint32_t, NotificationConstant::SWITCH_STATE>> reminderInfos;
5256+ EXPECT_TRUE(NotificationPreferences::GetInstance()->GetReminderInfoForBundles(bundleOptions,
5257+ reminderInfos, 100, 59));
5258+ ASSERT_EQ(1u, reminderInfos.size());
5259+ EXPECT_EQ(40u, reminderInfos[0].first);
5260+ EXPECT_EQ(NotificationConstant::SWITCH_STATE::USER_MODIFIED_ON, reminderInfos[0].second);
5261+}
5262+ 
5206} // namespace Notification5263} // namespace Notification
5207} // namespace OHOS5264} // namespace OHOS