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 return false;
622 }
623 uint8_t leftSnoozeTimes = GetSnoozeTimesDynamic();
624 if (leftSnoozeTimes > 0 && (GetTimeInterval() > 0)) {
625 ANSR_LOGI("Left snooze times: %{public}d, update next triggerTime", leftSnoozeTimes);
626 SetTriggerTimeInMilli(GetTriggerTimeInMilli() + GetTimeInterval() * MILLI_SECONDS);
627 SetSnoozeTimesDynamic(--leftSnoozeTimes);
628 } else {
629 SetSnoozeTimesDynamic(GetSnoozeTimes());
630 if ((repeatMonth_ == 0 || repeatDay_ == 0) && (repeatDaysOfWeek_ == 0)) {
631 ANSR_LOGI("Not a day repeat reminder, no need to update to next trigger time.");
632 SetTriggerTimeInMilli(INVALID_LONG_LONG_VALUE);
633 return false;
634 } else {
635 uint64_t nextTriggerTime = GetNextTriggerTime();
636 if (nextTriggerTime != INVALID_LONG_LONG_VALUE) {
637 ANSR_LOGI("Set next trigger time successful, reset dynamic snoozeTimes");
638 SetTriggerTimeInMilli(nextTriggerTime);
639 } else {
640 ANSR_LOGW("Set next trigger time invalidate");
641 SetExpired(true);
642 return false;
643 }
644 }
645 }
646 return true;
647 }
648
PreGetNextTriggerTimeIgnoreSnooze(bool ignoreRepeat,bool forceToGetNext)649 uint64_t ReminderRequestCalendar::PreGetNextTriggerTimeIgnoreSnooze(bool ignoreRepeat, bool forceToGetNext)
650 {
651 if (ignoreRepeat || (repeatMonth_ > 0 && repeatDay_ > 0) || (repeatDaysOfWeek_ > 0)) {
652 return GetNextTriggerTime(true);
653 } else {
654 return INVALID_LONG_LONG_VALUE;
655 }
656 }
657
Marshalling(Parcel & parcel) const658 bool ReminderRequestCalendar::Marshalling(Parcel &parcel) const
659 {
660 if (ReminderRequest::Marshalling(parcel)) {
661 // write int
662 WRITE_UINT16_RETURN_FALSE_LOG(parcel, year_, "year");
663 WRITE_UINT8_RETURN_FALSE_LOG(parcel, month_, "month");
664 WRITE_UINT8_RETURN_FALSE_LOG(parcel, day_, "day");
665 WRITE_UINT8_RETURN_FALSE_LOG(parcel, hour_, "hour");
666 WRITE_UINT8_RETURN_FALSE_LOG(parcel, minute_, "minute");
667 WRITE_UINT8_RETURN_FALSE_LOG(parcel, second_, "second");
668 WRITE_UINT16_RETURN_FALSE_LOG(parcel, repeatMonth_, "repeatMonth");
669 WRITE_UINT32_RETURN_FALSE_LOG(parcel, repeatDay_, "repeatDay");
670 WRITE_UINT64_RETURN_FALSE_LOG(parcel, durationTime_, "durationTime");
671 WRITE_UINT64_RETURN_FALSE_LOG(parcel, startDateTime_, "startDateTime");
672 WRITE_UINT64_RETURN_FALSE_LOG(parcel, endDateTime_, "endDateTime");
673 WRITE_UINT64_RETURN_FALSE_LOG(parcel, lastStartDateTime_, "lastStartDateTime");
674 WRITE_UINT16_RETURN_FALSE_LOG(parcel, firstDesignateYear_, "firstDesignateYear");
675 WRITE_UINT8_RETURN_FALSE_LOG(parcel, firstDesignateMonth_, "firstDesignateMonth");
676 WRITE_UINT8_RETURN_FALSE_LOG(parcel, firstDesignateDay_, "firstDesignateDay");
677 WRITE_UINT8_RETURN_FALSE_LOG(parcel, repeatDaysOfWeek_, "repeatDaysOfWeek");
678
679 bool rruleFlag = rruleWantAgentInfo_ == nullptr ? 0 : 1;
680 WRITE_BOOL_RETURN_FALSE_LOG(parcel, rruleFlag, "rruleFlag");
681 if (rruleWantAgentInfo_ != nullptr) {
682 WRITE_STRING_RETURN_FALSE_LOG(parcel, rruleWantAgentInfo_->pkgName, "rruleWantAgentInfo's pkgName");
683 WRITE_STRING_RETURN_FALSE_LOG(parcel, rruleWantAgentInfo_->abilityName, "rruleWantAgentInfo's abilityName");
684 WRITE_STRING_RETURN_FALSE_LOG(parcel, rruleWantAgentInfo_->uri, "rruleWantAgentInfo's uri");
685 }
686 return true;
687 }
688 return false;
689 }
690
Unmarshalling(Parcel & parcel)691 ReminderRequestCalendar *ReminderRequestCalendar::Unmarshalling(Parcel &parcel)
692 {
693 ANSR_LOGD("New calendar");
694 auto objptr = new (std::nothrow) ReminderRequestCalendar();
695 if (objptr == nullptr) {
696 ANS_LOGE("Failed to create reminder calendar due to no memory.");
697 return objptr;
698 }
699 if (!objptr->ReadFromParcel(parcel)) {
700 delete objptr;
701 objptr = nullptr;
702 }
703 return objptr;
704 }
705
ReadFromParcel(Parcel & parcel)706 bool ReminderRequestCalendar::ReadFromParcel(Parcel &parcel)
707 {
708 if (ReminderRequest::ReadFromParcel(parcel)) {
709 // read int
710 READ_UINT16_RETURN_FALSE_LOG(parcel, year_, "year");
711 READ_UINT8_RETURN_FALSE_LOG(parcel, month_, "month");
712 READ_UINT8_RETURN_FALSE_LOG(parcel, day_, "day");
713 READ_UINT8_RETURN_FALSE_LOG(parcel, hour_, "hour");
714 READ_UINT8_RETURN_FALSE_LOG(parcel, minute_, "minute");
715 READ_UINT8_RETURN_FALSE_LOG(parcel, second_, "second");
716 READ_UINT16_RETURN_FALSE_LOG(parcel, repeatMonth_, "repeatMonth");
717 READ_UINT32_RETURN_FALSE_LOG(parcel, repeatDay_, "repeatDay");
718 READ_UINT64_RETURN_FALSE_LOG(parcel, durationTime_, "durationTime");
719 READ_UINT64_RETURN_FALSE_LOG(parcel, startDateTime_, "startDateTime");
720 READ_UINT64_RETURN_FALSE_LOG(parcel, endDateTime_, "endDateTime");
721 READ_UINT64_RETURN_FALSE_LOG(parcel, lastStartDateTime_, "lastStartDateTime");
722
723 InitDateTime();
724
725 READ_UINT16_RETURN_FALSE_LOG(parcel, firstDesignateYear_, "firstDesignateYear");
726 READ_UINT8_RETURN_FALSE_LOG(parcel, firstDesignateMonth_, "firstDesignateMonth");
727 READ_UINT8_RETURN_FALSE_LOG(parcel, firstDesignateDay_, "firstDesignateDay");
728 READ_UINT8_RETURN_FALSE_LOG(parcel, repeatDaysOfWeek_, "repeatDaysOfWeek");
729
730 bool rruleFlag = false;
731 READ_BOOL_RETURN_FALSE_LOG(parcel, rruleFlag, "rruleFlag");
732 if (rruleFlag) {
733 rruleWantAgentInfo_ = std::make_shared<WantAgentInfo>();
734 READ_STRING_RETURN_FALSE_LOG(parcel, rruleWantAgentInfo_->pkgName, "rruleWantAgentInfo's pkgName");
735 READ_STRING_RETURN_FALSE_LOG(parcel, rruleWantAgentInfo_->abilityName, "rruleWantAgentInfo's abilityName");
736 READ_STRING_RETURN_FALSE_LOG(parcel, rruleWantAgentInfo_->uri, "rruleWantAgentInfo's uri");
737 }
738 return true;
739 }
740 return false;
741 }
742
SetDateTime(const uint64_t time)743 void ReminderRequestCalendar::SetDateTime(const uint64_t time)
744 {
745 time_t t = static_cast<time_t>(time / MILLI_SECONDS);
746 struct tm dateTime;
747 (void)localtime_r(&t, &dateTime);
748
749 year_ = static_cast<uint16_t>(GetActualTime(TimeTransferType::YEAR, dateTime.tm_year));
750 month_ = static_cast<uint8_t>(GetActualTime(TimeTransferType::MONTH, dateTime.tm_mon));
751 day_ = static_cast<uint8_t>(dateTime.tm_mday);
752 hour_ = static_cast<uint8_t>(dateTime.tm_hour);
753 minute_ = static_cast<uint8_t>(dateTime.tm_min);
754 second_ = static_cast<uint8_t>(dateTime.tm_sec);
755 startDateTime_ = time;
756 }
757
SetEndDateTime(const uint64_t time)758 bool ReminderRequestCalendar::SetEndDateTime(const uint64_t time)
759 {
760 if (time < startDateTime_) {
761 return false;
762 }
763 endDateTime_ = time;
764 durationTime_ = endDateTime_ - startDateTime_;
765 return true;
766 }
767
GetDateTime() const768 uint64_t ReminderRequestCalendar::GetDateTime() const
769 {
770 return startDateTime_;
771 }
772
GetEndDateTime() const773 uint64_t ReminderRequestCalendar::GetEndDateTime() const
774 {
775 return endDateTime_;
776 }
777
SetLastStartDateTime(const uint64_t time)778 void ReminderRequestCalendar::SetLastStartDateTime(const uint64_t time)
779 {
780 lastStartDateTime_ = time;
781 }
782
GetLastStartDateTime() const783 uint64_t ReminderRequestCalendar::GetLastStartDateTime() const
784 {
785 return lastStartDateTime_;
786 }
787
SerializationRRule()788 std::string ReminderRequestCalendar::SerializationRRule()
789 {
790 constexpr int32_t INDENT = -1;
791 if (rruleWantAgentInfo_ == nullptr) {
792 return "";
793 }
794 nlohmann::json root;
795 root["pkgName"] = rruleWantAgentInfo_->pkgName;
796 root["abilityName"] = rruleWantAgentInfo_->abilityName;
797 root["uri"] = rruleWantAgentInfo_->uri;
798 std::string str = root.dump(INDENT, ' ', false, nlohmann::json::error_handler_t::replace);
799 return str;
800 }
801
SerializationExcludeDates()802 std::string ReminderRequestCalendar::SerializationExcludeDates()
803 {
804 constexpr int32_t INDENT = -1;
805 nlohmann::json root;
806 root["excludeDates"] = nlohmann::json::array();
807 for (auto date : excludeDates_) {
808 root["excludeDates"].push_back(date);
809 }
810 std::string str = root.dump(INDENT, ' ', false, nlohmann::json::error_handler_t::replace);
811 return str;
812 }
813
DeserializationRRule(const std::string & str)814 void ReminderRequestCalendar::DeserializationRRule(const std::string& str)
815 {
816 if (str.empty()) {
817 return;
818 }
819 if (!nlohmann::json::accept(str)) {
820 ANSR_LOGW("not a json string!");
821 return;
822 }
823 nlohmann::json root = nlohmann::json::parse(str, nullptr, false);
824 if (root.is_discarded()) {
825 ANSR_LOGW("parse json data failed!");
826 return;
827 }
828 if (!root.contains("pkgName") || !root["pkgName"].is_string() ||
829 !root.contains("abilityName") || !root["abilityName"].is_string() ||
830 !root.contains("uri") || !root["uri"].is_string()) {
831 return;
832 }
833
834 rruleWantAgentInfo_ = std::make_shared<WantAgentInfo>();
835 rruleWantAgentInfo_->pkgName = root["pkgName"].get<std::string>();
836 rruleWantAgentInfo_->abilityName = root["abilityName"].get<std::string>();
837 rruleWantAgentInfo_->uri = root["uri"].get<std::string>();
838 }
839
DeserializationExcludeDates(const std::string & str)840 void ReminderRequestCalendar::DeserializationExcludeDates(const std::string& str)
841 {
842 if (str.empty()) {
843 return;
844 }
845 if (!nlohmann::json::accept(str)) {
846 return;
847 }
848 nlohmann::json root = nlohmann::json::parse(str, nullptr, false);
849 if (root.is_discarded()) {
850 return;
851 }
852
853 if (!root.contains("excludeDates") || !root["excludeDates"].is_array()) {
854 return;
855 }
856 excludeDates_.clear();
857 for (auto date : root["excludeDates"]) {
858 if (date.is_number()) {
859 excludeDates_.insert(date.get<uint64_t>());
860 }
861 }
862 }
863 }
864 }
865