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