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