1 /* 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "reminder_request_calendar.h" 17 18 #include "ans_log_wrapper.h" 19 #include "nlohmann/json.hpp" 20 21 namespace OHOS { 22 namespace Notification { 23 const uint8_t ReminderRequestCalendar::DEFAULT_SNOOZE_TIMES = 3; 24 25 const uint8_t ReminderRequestCalendar::DAY_ARRAY[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 26 ReminderRequestCalendar(const tm & dateTime,const std::vector<uint8_t> & repeatMonths,const std::vector<uint8_t> & repeatDays,const std::vector<uint8_t> & daysOfWeek)27 ReminderRequestCalendar::ReminderRequestCalendar(const tm &dateTime, const std::vector<uint8_t> &repeatMonths, 28 const std::vector<uint8_t> &repeatDays, const std::vector<uint8_t> &daysOfWeek) 29 : ReminderRequest(ReminderRequest::ReminderType::CALENDAR) 30 { 31 // 1. record the information which designated by user at first time. 32 firstDesignateYear_ = static_cast<uint16_t>(GetActualTime(TimeTransferType::YEAR, dateTime.tm_year)); 33 firstDesignateMonth_ = static_cast<uint8_t>(GetActualTime(TimeTransferType::MONTH, dateTime.tm_mon)); 34 firstDesignateDay_ = dateTime.tm_mday; 35 SetRepeatMonths(repeatMonths); 36 SetRepeatDaysOfMonth(repeatDays); 37 SetRepeatDaysOfWeek(true, daysOfWeek); 38 SetSnoozeTimes(DEFAULT_SNOOZE_TIMES); 39 40 // 2. should SetNextTriggerTime() after constructor 41 InitDateTime(dateTime); 42 } 43 ReminderRequestCalendar(const ReminderRequestCalendar & other)44 ReminderRequestCalendar::ReminderRequestCalendar(const ReminderRequestCalendar &other) : ReminderRequest(other) 45 { 46 dateTime_ = other.dateTime_; 47 firstDesignateYear_ = other.firstDesignateYear_; 48 firstDesignateMonth_ = other.firstDesignateMonth_; 49 firstDesignateDay_ = other.firstDesignateDay_; 50 year_ = other.year_; 51 month_ = other.month_; 52 day_ = other.day_; 53 hour_ = other.hour_; 54 minute_ = other.minute_; 55 second_ = other.second_; 56 repeatMonth_ = other.repeatMonth_; 57 repeatDay_ = other.repeatDay_; 58 repeatDaysOfWeek_ = other.repeatDaysOfWeek_; 59 rruleWantAgentInfo_ = other.rruleWantAgentInfo_; 60 durationTime_ = other.durationTime_; 61 startDateTime_ = other.startDateTime_; 62 endDateTime_ = other.endDateTime_; 63 excludeDates_ = other.excludeDates_; 64 lastStartDateTime_ = other.lastStartDateTime_; 65 } 66 SetRRuleWantAgentInfo(const std::shared_ptr<WantAgentInfo> & wantAgentInfo)67 void ReminderRequestCalendar::SetRRuleWantAgentInfo(const std::shared_ptr<WantAgentInfo> &wantAgentInfo) 68 { 69 rruleWantAgentInfo_ = wantAgentInfo; 70 } 71 AddExcludeDate(const uint64_t date)72 void ReminderRequestCalendar::AddExcludeDate(const uint64_t date) 73 { 74 time_t t = static_cast<time_t>(date / MILLI_SECONDS); 75 struct tm dateTime; 76 (void)localtime_r(&t, &dateTime); 77 dateTime.tm_hour = 0; 78 dateTime.tm_min = 0; 79 dateTime.tm_sec = 0; 80 const time_t target = mktime(&dateTime); 81 if (target == -1) { 82 ANSR_LOGW("error exclude date"); 83 return; 84 } 85 excludeDates_.insert(ReminderRequest::GetDurationSinceEpochInMilli(target)); 86 } 87 DelExcludeDates()88 void ReminderRequestCalendar::DelExcludeDates() 89 { 90 excludeDates_.clear(); 91 } 92 GetExcludeDates() const93 std::vector<uint64_t> ReminderRequestCalendar::GetExcludeDates() const 94 { 95 std::vector<uint64_t> excludeDates; 96 for (auto date : excludeDates_) { 97 excludeDates.push_back(date); 98 } 99 return excludeDates; 100 } 101 IsInExcludeDate() const102 bool ReminderRequestCalendar::IsInExcludeDate() const 103 { 104 time_t t = static_cast<time_t>(startDateTime_ / MILLI_SECONDS); 105 struct tm dateTime; 106 (void)localtime_r(&t, &dateTime); 107 dateTime.tm_hour = 0; 108 dateTime.tm_min = 0; 109 dateTime.tm_sec = 0; 110 const time_t target = mktime(&dateTime); 111 if (target == -1) { 112 ANSR_LOGW("error start date time"); 113 return false; 114 } 115 uint64_t notificationTime = ReminderRequest::GetDurationSinceEpochInMilli(target); 116 if (excludeDates_.find(notificationTime) != excludeDates_.end()) { 117 ANSR_LOGI("Reminder[%{public}d] trigger time is in exclude date", GetReminderId()); 118 return true; 119 } 120 return false; 121 } 122 GetRRuleWantAgentInfo()123 std::shared_ptr<ReminderRequest::WantAgentInfo> ReminderRequestCalendar::GetRRuleWantAgentInfo() 124 { 125 return rruleWantAgentInfo_; 126 } 127 SetRepeatDay(const uint32_t repeatDay)128 void ReminderRequestCalendar::SetRepeatDay(const uint32_t repeatDay) 129 { 130 repeatDay_ = repeatDay; 131 } 132 SetRepeatMonth(const uint16_t repeatMonth)133 void ReminderRequestCalendar::SetRepeatMonth(const uint16_t repeatMonth) 134 { 135 repeatMonth_ = repeatMonth; 136 } 137 SetFirstDesignateYear(const uint16_t firstDesignateYear)138 void ReminderRequestCalendar::SetFirstDesignateYear(const uint16_t firstDesignateYear) 139 { 140 firstDesignateYear_ = firstDesignateYear; 141 } 142 SetFirstDesignageMonth(const uint16_t firstDesignateMonth)143 void ReminderRequestCalendar::SetFirstDesignageMonth(const uint16_t firstDesignateMonth) 144 { 145 firstDesignateMonth_ = firstDesignateMonth; 146 } 147 SetFirstDesignateDay(const uint16_t firstDesignateDay)148 void ReminderRequestCalendar::SetFirstDesignateDay(const uint16_t firstDesignateDay) 149 { 150 firstDesignateDay_ = firstDesignateDay; 151 } 152 SetYear(const uint16_t year)153 void ReminderRequestCalendar::SetYear(const uint16_t year) 154 { 155 year_ = year; 156 } 157 SetMonth(const uint8_t month)158 void ReminderRequestCalendar::SetMonth(const uint8_t month) 159 { 160 month_ = month; 161 } 162 SetDay(const uint8_t day)163 void ReminderRequestCalendar::SetDay(const uint8_t day) 164 { 165 day_ = day; 166 } 167 SetHour(const uint8_t hour)168 void ReminderRequestCalendar::SetHour(const uint8_t hour) 169 { 170 hour_ = hour; 171 } 172 SetMinute(const uint8_t minute)173 void ReminderRequestCalendar::SetMinute(const uint8_t minute) 174 { 175 minute_ = minute; 176 } 177 InitTriggerTime()178 bool ReminderRequestCalendar::InitTriggerTime() 179 { 180 uint64_t nextTriggerTime = INVALID_LONG_LONG_VALUE; 181 uint64_t nowInMilli = GetNowInstantMilli(); 182 if ((startDateTime_ <= nowInMilli) && (nowInMilli <= endDateTime_)) { 183 nextTriggerTime = nowInMilli + DEFAULT_DELAY_TIME; 184 } else if (startDateTime_ > nowInMilli) { 185 nextTriggerTime = startDateTime_; 186 } else if (endDateTime_ < nowInMilli && IsRepeatReminder()) { 187 nextTriggerTime = GetNextTriggerTime(); 188 } else { 189 return false; 190 } 191 lastStartDateTime_ = startDateTime_; 192 SetTriggerTimeInMilli(nextTriggerTime); 193 return true; 194 } 195 SetNextTriggerTime()196 bool ReminderRequestCalendar::SetNextTriggerTime() 197 { 198 hour_ = static_cast<uint8_t>(dateTime_.tm_hour); 199 minute_ = static_cast<uint8_t>(dateTime_.tm_min); 200 uint64_t nextTriggerTime = INVALID_LONG_LONG_VALUE; 201 if ((nextTriggerTime = GetNextTriggerTime()) != INVALID_LONG_LONG_VALUE) { 202 time_t target = static_cast<time_t>(nextTriggerTime / MILLI_SECONDS); 203 (void)localtime_r(&target, &dateTime_); 204 } else { 205 ANSR_LOGW("Not exist next trigger time, please check the param of ReminderRequestCalendar constructor."); 206 return false; 207 } 208 209 // set the time information (used to transfer to proxy service) which is decided to trigger firstly. 210 year_ = static_cast<uint16_t>(GetActualTime(TimeTransferType::YEAR, dateTime_.tm_year)); 211 month_ = static_cast<uint8_t>(GetActualTime(TimeTransferType::MONTH, dateTime_.tm_mon)); 212 day_ = static_cast<uint8_t>(dateTime_.tm_mday); 213 second_ = 0; 214 SetTriggerTimeInMilli(nextTriggerTime); 215 return true; 216 } 217 GetDaysOfMonth(const uint16_t & year,const uint8_t & month)218 uint8_t ReminderRequestCalendar::GetDaysOfMonth(const uint16_t &year, const uint8_t &month) 219 { 220 uint8_t days; 221 if (month == FEBRUARY) { 222 days = ((((year % LEAP_PARAM_MIN == 0) && (year % LEAP_PARAM_MAX != 0)) || (year % SOLAR_YEAR == 0)) 223 ? LEAP_MONTH : NON_LEAP_MONTH); 224 } else { 225 days = DAY_ARRAY[month - 1]; 226 } 227 return days; 228 } 229 GetNextDay(const uint16_t & settedYear,const uint8_t & settedMonth,const tm & now,const tm & target) const230 uint8_t ReminderRequestCalendar::GetNextDay( 231 const uint16_t &settedYear, const uint8_t &settedMonth, const tm &now, const tm &target) const 232 { 233 uint32_t repeatDayTmp = repeatDay_; 234 uint8_t daysOfSpecialMonth = GetDaysOfMonth(settedYear, settedMonth); 235 uint8_t setDayTmp = INVALID_U8_VALUE; 236 for (uint8_t i = 1; i <= daysOfSpecialMonth; i++) { 237 if ((repeatDayTmp & (1 << (i - 1))) > 0) { 238 struct tm setTime; 239 setTime.tm_year = GetCTime(TimeTransferType::YEAR, settedYear); 240 setTime.tm_mon = GetCTime(TimeTransferType::MONTH, settedMonth); 241 setTime.tm_mday = static_cast<int>(i); 242 setTime.tm_hour = target.tm_hour; 243 setTime.tm_min = target.tm_min; 244 setTime.tm_sec = target.tm_sec; 245 setTime.tm_isdst = -1; 246 247 struct tm nowTime; 248 nowTime.tm_year = now.tm_year; 249 nowTime.tm_mon = now.tm_mon; 250 nowTime.tm_mday = now.tm_mday; 251 nowTime.tm_hour = now.tm_hour; 252 nowTime.tm_min = now.tm_min; 253 nowTime.tm_sec = now.tm_sec; 254 nowTime.tm_isdst = -1; 255 256 if (mktime(&nowTime) >= mktime(&setTime)) { 257 continue; 258 } else { 259 setDayTmp = i; 260 return setDayTmp; 261 } 262 } 263 } 264 return setDayTmp; 265 } 266 CheckCalenderIsExpired(const uint64_t now)267 bool ReminderRequestCalendar::CheckCalenderIsExpired(const uint64_t now) 268 { 269 if (IsInExcludeDate()) { 270 return false; 271 } 272 if (now <= (lastStartDateTime_ + durationTime_) && now >= lastStartDateTime_) { 273 ANSR_LOGI("now: %{public}" PRIu64 ", start: %{public}" PRIu64 ", end: %{public}" PRIu64 "", 274 now, lastStartDateTime_, lastStartDateTime_ + durationTime_); 275 return true; 276 } 277 if (now <= endDateTime_ && now >= startDateTime_) { 278 ANSR_LOGI("now: %{public}" PRIu64 ", start: %{public}" PRIu64 ", end: %{public}" PRIu64 "", 279 now, startDateTime_, endDateTime_); 280 return true; 281 } 282 return false; 283 } 284 OnDateTimeChange()285 bool ReminderRequestCalendar::OnDateTimeChange() 286 { 287 if (IsExpired()) { 288 return false; 289 } 290 if (startDateTime_ == endDateTime_) { 291 return ReminderRequest::OnDateTimeChange(); 292 } 293 uint64_t now = GetNowInstantMilli(); 294 if (now == 0) { 295 ANSR_LOGE("get now time failed"); 296 return false; 297 } 298 if (CheckCalenderIsExpired(now)) { 299 return GetTriggerTimeInMilli() <= now; 300 } else { 301 uint64_t triggerTime = GetNextTriggerTime(true); 302 SetTriggerTimeInMilli(triggerTime); 303 return false; 304 } 305 } 306 IsRepeat() const307 bool ReminderRequestCalendar::IsRepeat() const 308 { 309 return (repeatMonth_ > 0 && repeatDay_ > 0) || (repeatDaysOfWeek_ > 0); 310 } 311 CheckExcludeDate()312 bool ReminderRequestCalendar::CheckExcludeDate() 313 { 314 if (!IsRepeat()) { 315 // not repeat reminder 316 return false; 317 } 318 319 if (IsInExcludeDate()) { 320 // in exclude date 321 uint64_t triggerTime = GetNextTriggerTime(true); 322 SetTriggerTimeInMilli(triggerTime); 323 return true; 324 } 325 return false; 326 } 327 IsPullUpService()328 bool ReminderRequestCalendar::IsPullUpService() 329 { 330 if (rruleWantAgentInfo_ == nullptr) { 331 return false; 332 } 333 334 uint64_t now = GetNowInstantMilli(); 335 if (now == 0) { 336 ANSR_LOGE("get now time failed"); 337 return false; 338 } 339 340 if (now >= startDateTime_) { 341 return true; 342 } 343 return false; 344 } 345 IsNeedNotification()346 bool ReminderRequestCalendar::IsNeedNotification() 347 { 348 uint64_t now = GetNowInstantMilli(); 349 if (now == 0) { 350 ANSR_LOGE("get now time failed"); 351 return false; 352 } 353 if ((now <= endDateTime_ && now >= startDateTime_) || 354 (startDateTime_ == endDateTime_)) { 355 return true; 356 } 357 uint64_t triggerTime = GetNextTriggerTime(true); 358 SetTriggerTimeInMilli(triggerTime); 359 return false; 360 } 361 CalcLastStartDateTime()362 void ReminderRequestCalendar::CalcLastStartDateTime() 363 { 364 time_t t; 365 (void)time(&t); 366 struct tm nowTime; 367 (void)localtime_r(&t, &nowTime); 368 369 t = static_cast<time_t>(startDateTime_/MILLI_SECONDS); 370 struct tm startTime; 371 (void)localtime_r(&t, &startTime); 372 373 startTime.tm_year = nowTime.tm_year; 374 startTime.tm_mon = nowTime.tm_mon; 375 startTime.tm_mday = nowTime.tm_mday; 376 time_t target = mktime(&startTime); 377 if (target != -1) { 378 lastStartDateTime_ = ReminderRequest::GetDurationSinceEpochInMilli(target); 379 } 380 } 381 GetNextTriggerTime(const bool updateLast)382 uint64_t ReminderRequestCalendar::GetNextTriggerTime(const bool updateLast) 383 { 384 uint64_t triggerTimeInMilli = INVALID_LONG_LONG_VALUE; 385 time_t now; 386 (void)time(&now); // unit is seconds. 387 struct tm nowTime; 388 (void)localtime_r(&now, &nowTime); 389 nowTime.tm_sec = 0; 390 struct tm tarTime; 391 tarTime.tm_year = GetCTime(TimeTransferType::YEAR, firstDesignateYear_); 392 tarTime.tm_mon = GetCTime(TimeTransferType::MONTH, firstDesignateMonth_); 393 tarTime.tm_mday = firstDesignateDay_; 394 tarTime.tm_hour = hour_; 395 tarTime.tm_min = minute_; 396 tarTime.tm_sec = 0; 397 tarTime.tm_isdst = -1; 398 const time_t target = mktime(&tarTime); 399 ANSR_LOGD("Now time is: %{public}s", GetDateTimeInfo(now).c_str()); 400 if (repeatMonth_ > 0 && repeatDay_ > 0) { 401 triggerTimeInMilli = GetNextTriggerTimeAsRepeatReminder(nowTime, tarTime); 402 startDateTime_ = triggerTimeInMilli; 403 endDateTime_ = triggerTimeInMilli + durationTime_; 404 } else if (repeatDaysOfWeek_ > 0 && (target <= now)) { 405 nowTime.tm_hour = tarTime.tm_hour; 406 nowTime.tm_min = tarTime.tm_min; 407 nowTime.tm_sec = tarTime.tm_sec; 408 nowTime.tm_isdst = tarTime.tm_isdst; 409 const time_t tar = mktime(&nowTime); 410 triggerTimeInMilli = GetNextDaysOfWeek(now, tar); 411 startDateTime_ = triggerTimeInMilli; 412 endDateTime_ = triggerTimeInMilli + durationTime_; 413 } else { 414 ANSR_LOGD("tarTime: %{public}d-%{public}d-%{public}d %{public}d:%{public}d:%{public}d", 415 tarTime.tm_year, tarTime.tm_mon, tarTime.tm_mday, tarTime.tm_hour, tarTime.tm_min, tarTime.tm_sec); 416 if (target == -1) { 417 ANSR_LOGW("mktime return error."); 418 } 419 if (now < target) { 420 triggerTimeInMilli = ReminderRequest::GetDurationSinceEpochInMilli(target); 421 ANSR_LOGD("Next calendar time:%{public}s", GetDateTimeInfo(target).c_str()); 422 } 423 } 424 if (updateLast) { 425 lastStartDateTime_ = startDateTime_; 426 } else { 427 CalcLastStartDateTime(); 428 } 429 return triggerTimeInMilli; 430 } 431 GetNextTriggerTimeAsRepeatReminder(const tm & nowTime,const tm & tarTime) const432 uint64_t ReminderRequestCalendar::GetNextTriggerTimeAsRepeatReminder(const tm &nowTime, const tm &tarTime) const 433 { 434 uint64_t triggerTimeInMilli = INVALID_LONG_LONG_VALUE; 435 uint16_t setYear = static_cast<uint16_t>(GetActualTime(TimeTransferType::YEAR, nowTime.tm_year)); 436 uint8_t setMonth = INVALID_U8_VALUE; 437 uint8_t setDay = INVALID_U8_VALUE; 438 uint8_t beginMonth = static_cast<uint8_t>(GetActualTime(TimeTransferType::MONTH, nowTime.tm_mon)); 439 uint8_t count = 1; 440 uint16_t repeatMonthTmp = repeatMonth_; 441 for (uint8_t i = beginMonth; i < (MAX_MONTHS_OF_YEAR + beginMonth + 1); i++) { 442 if ((repeatMonthTmp & (1 << ((i - 1) % MAX_MONTHS_OF_YEAR))) > 0) { 443 setMonth = (i % MAX_MONTHS_OF_YEAR); 444 setMonth = setMonth == 0 ? DECEMBER : setMonth; 445 if (count != 1) { 446 setYear = setMonth <= beginMonth ? setYear + 1 : setYear; 447 } 448 setDay = GetNextDay(setYear, setMonth, nowTime, tarTime); 449 } 450 if (setDay != INVALID_U8_VALUE) { 451 break; 452 } 453 count++; 454 } 455 if ((triggerTimeInMilli = GetTimeInstantMilli(setYear, setMonth, setDay, hour_, minute_, second_)) 456 != INVALID_LONG_LONG_VALUE) { 457 ANSR_LOGD("Next calendar time:%{public}hu/%{public}hhu/%{public}hhu %{public}hhu:%{public}hhu:%{public}hhu", 458 setYear, setMonth, setDay, hour_, minute_, second_); 459 } 460 return triggerTimeInMilli; 461 } 462 GetTimeInstantMilli(uint16_t year,uint8_t month,uint8_t day,uint8_t hour,uint8_t minute,uint8_t second) const463 uint64_t ReminderRequestCalendar::GetTimeInstantMilli( 464 uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) const 465 { 466 struct tm tar; 467 tar.tm_year = GetCTime(TimeTransferType::YEAR, year); 468 tar.tm_mon = GetCTime(TimeTransferType::MONTH, month); 469 tar.tm_mday = static_cast<int>(day); 470 tar.tm_hour = static_cast<int>(hour); 471 tar.tm_min = static_cast<int>(minute); 472 tar.tm_sec = static_cast<int>(second); 473 tar.tm_isdst = -1; 474 475 ANSR_LOGD("tar: %{public}d-%{public}d-%{public}d %{public}d:%{public}d:%{public}d", 476 tar.tm_year, tar.tm_mon, tar.tm_mday, tar.tm_hour, tar.tm_min, tar.tm_sec); 477 const time_t target = mktime(&tar); 478 if (target == -1) { 479 ANSR_LOGW("mktime return error."); 480 return INVALID_LONG_LONG_VALUE; 481 } 482 return ReminderRequest::GetDurationSinceEpochInMilli(target); 483 } 484 InitDateTime()485 void ReminderRequestCalendar::InitDateTime() 486 { 487 dateTime_.tm_year = GetCTime(TimeTransferType::YEAR, year_); 488 dateTime_.tm_mon = GetCTime(TimeTransferType::MONTH, month_); 489 dateTime_.tm_mday = static_cast<int>(day_); 490 dateTime_.tm_hour = static_cast<int>(hour_); 491 dateTime_.tm_min = static_cast<int>(minute_); 492 dateTime_.tm_sec = static_cast<int>(second_); 493 dateTime_.tm_isdst = -1; 494 } 495 InitDateTime(const tm & dateTime)496 void ReminderRequestCalendar::InitDateTime(const tm &dateTime) 497 { 498 dateTime_.tm_year = dateTime.tm_year; 499 dateTime_.tm_mon = dateTime.tm_mon; 500 dateTime_.tm_mday = dateTime.tm_mday; 501 dateTime_.tm_hour = dateTime.tm_hour; 502 dateTime_.tm_min = dateTime.tm_min; 503 dateTime_.tm_sec = dateTime.tm_sec; 504 dateTime_.tm_isdst = -1; 505 506 year_ = static_cast<uint16_t>(GetActualTime(TimeTransferType::YEAR, dateTime.tm_year)); 507 month_ = static_cast<uint8_t>(GetActualTime(TimeTransferType::MONTH, dateTime.tm_mon)); 508 day_ = static_cast<uint8_t>(dateTime.tm_mday); 509 hour_ = static_cast<uint8_t>(dateTime.tm_hour); 510 minute_ = static_cast<uint8_t>(dateTime.tm_min); 511 second_ = static_cast<uint8_t>(dateTime.tm_sec); 512 513 time_t time = mktime(&dateTime_); 514 if (time == -1) { 515 startDateTime_ = 0; 516 } else { 517 startDateTime_ = ReminderRequest::GetDurationSinceEpochInMilli(time); 518 endDateTime_ = startDateTime_; 519 } 520 } 521 IsRepeatReminder() const522 bool ReminderRequestCalendar::IsRepeatReminder() const 523 { 524 return (repeatMonth_ > 0 && repeatDay_ > 0) || (repeatDaysOfWeek_ > 0) 525 || (GetTimeInterval() > 0 && GetSnoozeTimes() > 0); 526 } 527 IsRepeatMonth(uint8_t month) const528 bool ReminderRequestCalendar::IsRepeatMonth(uint8_t month) const 529 { 530 if (month > MAX_MONTHS_OF_YEAR) { 531 return false; 532 } 533 return (repeatMonth_ & (1 << (month - 1))) > 0; 534 } 535 IsRepeatDay(uint8_t day) const536 bool ReminderRequestCalendar::IsRepeatDay(uint8_t day) const 537 { 538 if (day > MAX_DAYS_OF_MONTH) { 539 return false; 540 } 541 return (repeatDay_ & (1 << (day - 1))) > 0; 542 } 543 SetDay(const uint8_t & day,const bool & isSet)544 void ReminderRequestCalendar::SetDay(const uint8_t &day, const bool &isSet) 545 { 546 if (day < 1 || day > MAX_DAYS_OF_MONTH) { 547 return; 548 } 549 if (isSet) { 550 repeatDay_ |= 1 << (day - 1); 551 } else { 552 repeatDay_ &= ~(1 << (day - 1)); 553 } 554 } 555 SetMonth(const uint8_t & month,const bool & isSet)556 void ReminderRequestCalendar::SetMonth(const uint8_t &month, const bool &isSet) 557 { 558 if (month < JANUARY || month > DECEMBER) { 559 return; 560 } 561 if (isSet) { 562 repeatMonth_ |= 1 << (month - 1); 563 } else { 564 repeatMonth_ &= ~ (1 << (month - 1)); 565 } 566 } 567 SetRepeatMonths(const std::vector<uint8_t> & repeatMonths)568 void ReminderRequestCalendar::SetRepeatMonths(const std::vector<uint8_t> &repeatMonths) 569 { 570 if (repeatMonths.size() > MAX_MONTHS_OF_YEAR) { 571 ANSR_LOGW("The length of repeat months array should not larger than %{public}hhu", MAX_MONTHS_OF_YEAR); 572 return; 573 } 574 repeatMonth_ = 0; 575 for (auto it = repeatMonths.begin(); it != repeatMonths.end(); ++it) { 576 SetMonth((*it), true); 577 } 578 } 579 SetRepeatDaysOfMonth(const std::vector<uint8_t> & repeatDays)580 void ReminderRequestCalendar::SetRepeatDaysOfMonth(const std::vector<uint8_t> &repeatDays) 581 { 582 if (repeatDays.size() > MAX_DAYS_OF_MONTH) { 583 ANSR_LOGW("The length of repeat days array should not larger than %{public}hhu", MAX_DAYS_OF_MONTH); 584 return; 585 } 586 repeatDay_ = 0; 587 for (auto it = repeatDays.begin(); it != repeatDays.end(); ++it) { 588 SetDay((*it), true); 589 } 590 } 591 GetRepeatMonths() const592 std::vector<uint8_t> ReminderRequestCalendar::GetRepeatMonths() const 593 { 594 std::vector<uint8_t> repeatMonths; 595 for (int32_t i = 0; i < MAX_MONTHS_OF_YEAR; i++) { 596 if (IsRepeatMonth(i + 1)) { 597 repeatMonths.push_back(i + 1); 598 } 599 } 600 return repeatMonths; 601 } 602 GetRepeatDays() const603 std::vector<uint8_t> ReminderRequestCalendar::GetRepeatDays() const 604 { 605 std::vector<uint8_t> repeatDays; 606 for (int32_t i = 0; i < MAX_DAYS_OF_MONTH; i++) { 607 if (IsRepeatDay(i + 1)) { 608 repeatDays.push_back(i + 1); 609 } 610 } 611 return repeatDays; 612 } 613 UpdateNextReminder()614 bool ReminderRequestCalendar::UpdateNextReminder() 615 { 616 ANSR_LOGD("UpdateNextReminder calendar time"); 617 if (!IsRepeatReminder()) { 618 ANSR_LOGI("No need to update next trigger time as it is an one-time reminder."); 619 SetSnoozeTimesDynamic(GetSnoozeTimes()); 620 SetTriggerTimeInMilli(INVALID_LONG_LONG_VALUE); 621 if (startDateTime_ == endDateTime_) { 622 SetExpired(true); 623 } 624 return false; 625 } 626 uint8_t leftSnoozeTimes = GetSnoozeTimesDynamic(); 627 if (leftSnoozeTimes > 0 && (GetTimeInterval() > 0)) { 628 ANSR_LOGI("Left snooze times: %{public}d, update next triggerTime", leftSnoozeTimes); 629 SetTriggerTimeInMilli(GetTriggerTimeInMilli() + GetTimeInterval() * MILLI_SECONDS); 630 SetSnoozeTimesDynamic(--leftSnoozeTimes); 631 } else { 632 SetSnoozeTimesDynamic(GetSnoozeTimes()); 633 if ((repeatMonth_ == 0 || repeatDay_ == 0) && (repeatDaysOfWeek_ == 0)) { 634 ANSR_LOGI("Not a day repeat reminder, no need to update to next trigger time."); 635 SetTriggerTimeInMilli(INVALID_LONG_LONG_VALUE); 636 if (startDateTime_ == endDateTime_) { 637 SetExpired(true); 638 } 639 return false; 640 } else { 641 uint64_t nextTriggerTime = GetNextTriggerTime(); 642 if (nextTriggerTime != INVALID_LONG_LONG_VALUE) { 643 ANSR_LOGI("Set next trigger time successful, reset dynamic snoozeTimes"); 644 SetTriggerTimeInMilli(nextTriggerTime); 645 } else { 646 ANSR_LOGW("Set next trigger time invalidate"); 647 SetExpired(true); 648 return false; 649 } 650 } 651 } 652 return true; 653 } 654 PreGetNextTriggerTimeIgnoreSnooze(bool ignoreRepeat,bool forceToGetNext)655 uint64_t ReminderRequestCalendar::PreGetNextTriggerTimeIgnoreSnooze(bool ignoreRepeat, bool forceToGetNext) 656 { 657 if (ignoreRepeat || (repeatMonth_ > 0 && repeatDay_ > 0) || (repeatDaysOfWeek_ > 0)) { 658 return GetNextTriggerTime(true); 659 } else { 660 return INVALID_LONG_LONG_VALUE; 661 } 662 } 663 Marshalling(Parcel & parcel) const664 bool ReminderRequestCalendar::Marshalling(Parcel &parcel) const 665 { 666 if (ReminderRequest::Marshalling(parcel)) { 667 // write int 668 WRITE_UINT16_RETURN_FALSE_LOG(parcel, year_, "year"); 669 WRITE_UINT8_RETURN_FALSE_LOG(parcel, month_, "month"); 670 WRITE_UINT8_RETURN_FALSE_LOG(parcel, day_, "day"); 671 WRITE_UINT8_RETURN_FALSE_LOG(parcel, hour_, "hour"); 672 WRITE_UINT8_RETURN_FALSE_LOG(parcel, minute_, "minute"); 673 WRITE_UINT8_RETURN_FALSE_LOG(parcel, second_, "second"); 674 WRITE_UINT16_RETURN_FALSE_LOG(parcel, repeatMonth_, "repeatMonth"); 675 WRITE_UINT32_RETURN_FALSE_LOG(parcel, repeatDay_, "repeatDay"); 676 WRITE_UINT64_RETURN_FALSE_LOG(parcel, durationTime_, "durationTime"); 677 WRITE_UINT64_RETURN_FALSE_LOG(parcel, startDateTime_, "startDateTime"); 678 WRITE_UINT64_RETURN_FALSE_LOG(parcel, endDateTime_, "endDateTime"); 679 WRITE_UINT64_RETURN_FALSE_LOG(parcel, lastStartDateTime_, "lastStartDateTime"); 680 WRITE_UINT16_RETURN_FALSE_LOG(parcel, firstDesignateYear_, "firstDesignateYear"); 681 WRITE_UINT8_RETURN_FALSE_LOG(parcel, firstDesignateMonth_, "firstDesignateMonth"); 682 WRITE_UINT8_RETURN_FALSE_LOG(parcel, firstDesignateDay_, "firstDesignateDay"); 683 WRITE_UINT8_RETURN_FALSE_LOG(parcel, repeatDaysOfWeek_, "repeatDaysOfWeek"); 684 685 bool rruleFlag = rruleWantAgentInfo_ == nullptr ? 0 : 1; 686 WRITE_BOOL_RETURN_FALSE_LOG(parcel, rruleFlag, "rruleFlag"); 687 if (rruleWantAgentInfo_ != nullptr) { 688 WRITE_STRING_RETURN_FALSE_LOG(parcel, rruleWantAgentInfo_->pkgName, "rruleWantAgentInfo's pkgName"); 689 WRITE_STRING_RETURN_FALSE_LOG(parcel, rruleWantAgentInfo_->abilityName, "rruleWantAgentInfo's abilityName"); 690 WRITE_STRING_RETURN_FALSE_LOG(parcel, rruleWantAgentInfo_->uri, "rruleWantAgentInfo's uri"); 691 } 692 return true; 693 } 694 return false; 695 } 696 Unmarshalling(Parcel & parcel)697 ReminderRequestCalendar *ReminderRequestCalendar::Unmarshalling(Parcel &parcel) 698 { 699 ANSR_LOGD("New calendar"); 700 auto objptr = new (std::nothrow) ReminderRequestCalendar(); 701 if (objptr == nullptr) { 702 ANS_LOGE("Failed to create reminder calendar due to no memory."); 703 return objptr; 704 } 705 if (!objptr->ReadFromParcel(parcel)) { 706 delete objptr; 707 objptr = nullptr; 708 } 709 return objptr; 710 } 711 ReadFromParcel(Parcel & parcel)712 bool ReminderRequestCalendar::ReadFromParcel(Parcel &parcel) 713 { 714 if (ReminderRequest::ReadFromParcel(parcel)) { 715 // read int 716 READ_UINT16_RETURN_FALSE_LOG(parcel, year_, "year"); 717 READ_UINT8_RETURN_FALSE_LOG(parcel, month_, "month"); 718 READ_UINT8_RETURN_FALSE_LOG(parcel, day_, "day"); 719 READ_UINT8_RETURN_FALSE_LOG(parcel, hour_, "hour"); 720 READ_UINT8_RETURN_FALSE_LOG(parcel, minute_, "minute"); 721 READ_UINT8_RETURN_FALSE_LOG(parcel, second_, "second"); 722 READ_UINT16_RETURN_FALSE_LOG(parcel, repeatMonth_, "repeatMonth"); 723 READ_UINT32_RETURN_FALSE_LOG(parcel, repeatDay_, "repeatDay"); 724 READ_UINT64_RETURN_FALSE_LOG(parcel, durationTime_, "durationTime"); 725 READ_UINT64_RETURN_FALSE_LOG(parcel, startDateTime_, "startDateTime"); 726 READ_UINT64_RETURN_FALSE_LOG(parcel, endDateTime_, "endDateTime"); 727 READ_UINT64_RETURN_FALSE_LOG(parcel, lastStartDateTime_, "lastStartDateTime"); 728 729 InitDateTime(); 730 731 READ_UINT16_RETURN_FALSE_LOG(parcel, firstDesignateYear_, "firstDesignateYear"); 732 READ_UINT8_RETURN_FALSE_LOG(parcel, firstDesignateMonth_, "firstDesignateMonth"); 733 READ_UINT8_RETURN_FALSE_LOG(parcel, firstDesignateDay_, "firstDesignateDay"); 734 READ_UINT8_RETURN_FALSE_LOG(parcel, repeatDaysOfWeek_, "repeatDaysOfWeek"); 735 736 bool rruleFlag = false; 737 READ_BOOL_RETURN_FALSE_LOG(parcel, rruleFlag, "rruleFlag"); 738 if (rruleFlag) { 739 rruleWantAgentInfo_ = std::make_shared<WantAgentInfo>(); 740 READ_STRING_RETURN_FALSE_LOG(parcel, rruleWantAgentInfo_->pkgName, "rruleWantAgentInfo's pkgName"); 741 READ_STRING_RETURN_FALSE_LOG(parcel, rruleWantAgentInfo_->abilityName, "rruleWantAgentInfo's abilityName"); 742 READ_STRING_RETURN_FALSE_LOG(parcel, rruleWantAgentInfo_->uri, "rruleWantAgentInfo's uri"); 743 } 744 return true; 745 } 746 return false; 747 } 748 SetDateTime(const uint64_t time)749 void ReminderRequestCalendar::SetDateTime(const uint64_t time) 750 { 751 time_t t = static_cast<time_t>(time / MILLI_SECONDS); 752 struct tm dateTime; 753 (void)localtime_r(&t, &dateTime); 754 755 year_ = static_cast<uint16_t>(GetActualTime(TimeTransferType::YEAR, dateTime.tm_year)); 756 month_ = static_cast<uint8_t>(GetActualTime(TimeTransferType::MONTH, dateTime.tm_mon)); 757 day_ = static_cast<uint8_t>(dateTime.tm_mday); 758 hour_ = static_cast<uint8_t>(dateTime.tm_hour); 759 minute_ = static_cast<uint8_t>(dateTime.tm_min); 760 second_ = static_cast<uint8_t>(dateTime.tm_sec); 761 startDateTime_ = time; 762 } 763 SetEndDateTime(const uint64_t time)764 bool ReminderRequestCalendar::SetEndDateTime(const uint64_t time) 765 { 766 if (time < startDateTime_) { 767 return false; 768 } 769 endDateTime_ = time; 770 durationTime_ = endDateTime_ - startDateTime_; 771 return true; 772 } 773 GetDateTime() const774 uint64_t ReminderRequestCalendar::GetDateTime() const 775 { 776 return startDateTime_; 777 } 778 GetEndDateTime() const779 uint64_t ReminderRequestCalendar::GetEndDateTime() const 780 { 781 return endDateTime_; 782 } 783 SetLastStartDateTime(const uint64_t time)784 void ReminderRequestCalendar::SetLastStartDateTime(const uint64_t time) 785 { 786 lastStartDateTime_ = time; 787 } 788 GetLastStartDateTime() const789 uint64_t ReminderRequestCalendar::GetLastStartDateTime() const 790 { 791 return lastStartDateTime_; 792 } 793 SerializationRRule()794 std::string ReminderRequestCalendar::SerializationRRule() 795 { 796 constexpr int32_t INDENT = -1; 797 if (rruleWantAgentInfo_ == nullptr) { 798 return ""; 799 } 800 nlohmann::json root; 801 root["pkgName"] = rruleWantAgentInfo_->pkgName; 802 root["abilityName"] = rruleWantAgentInfo_->abilityName; 803 root["uri"] = rruleWantAgentInfo_->uri; 804 std::string str = root.dump(INDENT, ' ', false, nlohmann::json::error_handler_t::replace); 805 return str; 806 } 807 SerializationExcludeDates()808 std::string ReminderRequestCalendar::SerializationExcludeDates() 809 { 810 constexpr int32_t INDENT = -1; 811 nlohmann::json root; 812 root["excludeDates"] = nlohmann::json::array(); 813 for (auto date : excludeDates_) { 814 root["excludeDates"].push_back(date); 815 } 816 std::string str = root.dump(INDENT, ' ', false, nlohmann::json::error_handler_t::replace); 817 return str; 818 } 819 DeserializationRRule(const std::string & str)820 void ReminderRequestCalendar::DeserializationRRule(const std::string& str) 821 { 822 if (str.empty()) { 823 return; 824 } 825 if (!nlohmann::json::accept(str)) { 826 ANSR_LOGW("not a json string!"); 827 return; 828 } 829 nlohmann::json root = nlohmann::json::parse(str, nullptr, false); 830 if (root.is_discarded()) { 831 ANSR_LOGW("parse json data failed!"); 832 return; 833 } 834 if (!root.contains("pkgName") || !root["pkgName"].is_string() || 835 !root.contains("abilityName") || !root["abilityName"].is_string() || 836 !root.contains("uri") || !root["uri"].is_string()) { 837 return; 838 } 839 840 rruleWantAgentInfo_ = std::make_shared<WantAgentInfo>(); 841 rruleWantAgentInfo_->pkgName = root["pkgName"].get<std::string>(); 842 rruleWantAgentInfo_->abilityName = root["abilityName"].get<std::string>(); 843 rruleWantAgentInfo_->uri = root["uri"].get<std::string>(); 844 } 845 DeserializationExcludeDates(const std::string & str)846 void ReminderRequestCalendar::DeserializationExcludeDates(const std::string& str) 847 { 848 if (str.empty()) { 849 return; 850 } 851 if (!nlohmann::json::accept(str)) { 852 return; 853 } 854 nlohmann::json root = nlohmann::json::parse(str, nullptr, false); 855 if (root.is_discarded()) { 856 return; 857 } 858 859 if (!root.contains("excludeDates") || !root["excludeDates"].is_array()) { 860 return; 861 } 862 excludeDates_.clear(); 863 for (auto date : root["excludeDates"]) { 864 if (date.is_number()) { 865 excludeDates_.insert(date.get<uint64_t>()); 866 } 867 } 868 } 869 } 870 } 871