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