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_alarm.h"
17
18 #include "ans_log_wrapper.h"
19
20 namespace OHOS {
21 namespace Notification {
22 const uint8_t ReminderRequestAlarm::MINUTES_PER_HOUR = 60;
23 const int8_t ReminderRequestAlarm::DEFAULT_SNOOZE_TIMES = 3;
24
ReminderRequestAlarm(uint8_t hour,uint8_t minute,const std::vector<uint8_t> daysOfWeek)25 ReminderRequestAlarm::ReminderRequestAlarm(uint8_t hour, uint8_t minute, const std::vector<uint8_t> daysOfWeek)
26 : ReminderRequest(ReminderRequest::ReminderType::ALARM)
27 {
28 SetSnoozeTimes(DEFAULT_SNOOZE_TIMES);
29 hour_ = hour;
30 minute_ = minute;
31 CheckParamValid();
32 SetRepeatDaysOfWeek(true, daysOfWeek);
33 SetTriggerTimeInMilli(GetNextTriggerTime(true));
34 }
35
ReminderRequestAlarm(const ReminderRequestAlarm & other)36 ReminderRequestAlarm::ReminderRequestAlarm(const ReminderRequestAlarm &other) : ReminderRequest(other)
37 {
38 hour_ = other.hour_;
39 minute_ = other.minute_;
40 repeatDaysOfWeek_ = other.repeatDaysOfWeek_;
41 ANSR_LOGD("hour_=%{public}d, minute_=%{public}d, repeatDaysOfWeek_=%{public}d",
42 hour_, minute_, other.repeatDaysOfWeek_);
43 }
44
CheckParamValid() const45 void ReminderRequestAlarm::CheckParamValid() const
46 {
47 if (hour_ >= HOURS_PER_DAY) {
48 ANSR_LOGE("setted hour is not between [0, 24)");
49 return;
50 }
51 if (minute_ >= MINUTES_PER_HOUR) {
52 ANSR_LOGE("setted minute is not between [0, 60)");
53 return;
54 }
55 }
56
IsRepeatReminder() const57 bool ReminderRequestAlarm::IsRepeatReminder() const
58 {
59 if ((repeatDaysOfWeek_ != 0) || ((GetTimeInterval() > 0) && (GetSnoozeTimes() > 0))) {
60 return true;
61 } else {
62 return false;
63 }
64 }
65
66
PreGetNextTriggerTimeIgnoreSnooze(bool ignoreRepeat,bool forceToGetNext)67 uint64_t ReminderRequestAlarm::PreGetNextTriggerTimeIgnoreSnooze(bool ignoreRepeat, bool forceToGetNext)
68 {
69 if (ignoreRepeat || (repeatDaysOfWeek_)) {
70 return GetNextTriggerTime(forceToGetNext);
71 } else {
72 return INVALID_LONG_LONG_VALUE;
73 }
74 }
75
GetNextTriggerTime(bool forceToGetNext) const76 uint64_t ReminderRequestAlarm::GetNextTriggerTime(bool forceToGetNext) const
77 {
78 time_t now;
79 (void)time(&now); // unit is seconds.
80 struct tm nowTime;
81 (void)localtime_r(&now, &nowTime);
82 ANSR_LOGD("Now: year=%{public}d, mon=%{public}d, day=%{public}d, hour=%{public}d, "
83 "min=%{public}d, sec=%{public}d, week=%{public}d, Target: tar_hour=%{public}d, tar_min=%{public}d",
84 GetActualTime(TimeTransferType::YEAR, nowTime.tm_year),
85 GetActualTime(TimeTransferType::MONTH, nowTime.tm_mon),
86 nowTime.tm_mday, nowTime.tm_hour, nowTime.tm_min, nowTime.tm_sec,
87 GetActualTime(TimeTransferType::WEEK, nowTime.tm_wday), hour_, minute_);
88
89 struct tm tar;
90 tar.tm_year = nowTime.tm_year;
91 tar.tm_mon = nowTime.tm_mon;
92 tar.tm_mday = nowTime.tm_mday;
93 tar.tm_hour = hour_;
94 tar.tm_min = minute_;
95 tar.tm_sec = 0;
96 tar.tm_isdst = -1;
97
98 const time_t target = mktime(&tar);
99 if (repeatDaysOfWeek_ > 0) {
100 return GetNextDaysOfWeek(now, target);
101 }
102
103 time_t nextTriggerTime = 0;
104 if (now >= target) {
105 if (forceToGetNext) {
106 nextTriggerTime = target + 1 * HOURS_PER_DAY * SECONDS_PER_HOUR;
107 }
108 } else {
109 nextTriggerTime = target;
110 }
111 return GetTriggerTime(now, nextTriggerTime);
112 }
113
SetHour(const uint8_t hour)114 void ReminderRequestAlarm::SetHour(const uint8_t hour)
115 {
116 hour_ = hour;
117 }
118
SetMinute(const uint8_t minute)119 void ReminderRequestAlarm::SetMinute(const uint8_t minute)
120 {
121 minute_ = minute;
122 }
123
GetHour() const124 uint8_t ReminderRequestAlarm::GetHour() const
125 {
126 return hour_;
127 }
128
GetMinute() const129 uint8_t ReminderRequestAlarm::GetMinute() const
130 {
131 return minute_;
132 }
133
UpdateNextReminder()134 bool ReminderRequestAlarm::UpdateNextReminder()
135 {
136 ANSR_LOGD("UpdateNextReminder alarm time");
137 if (IsRepeatReminder()) {
138 uint8_t letfSnoozeTimes = GetSnoozeTimesDynamic();
139 if ((letfSnoozeTimes > 0) && (GetTimeInterval() > 0)) {
140 ANSR_LOGI("Left times: %{public}d, update next triggerTime", GetSnoozeTimesDynamic());
141 SetTriggerTimeInMilli(GetTriggerTimeInMilli() + GetTimeInterval() * MILLI_SECONDS);
142 SetSnoozeTimesDynamic(--letfSnoozeTimes);
143 } else {
144 SetSnoozeTimesDynamic(GetSnoozeTimes());
145 if (repeatDaysOfWeek_ == 0) {
146 ANSR_LOGI("No need to update next triggerTime");
147 SetExpired(true);
148 return false;
149 }
150 uint64_t nextTriggerTime = GetNextTriggerTime(true);
151 if (nextTriggerTime != INVALID_LONG_LONG_VALUE) {
152 ANSR_LOGI("Set next trigger time successful, reset dynamic snoozeTimes");
153 SetTriggerTimeInMilli(nextTriggerTime);
154 } else {
155 ANSR_LOGW("Set reminder to expired");
156 SetExpired(true);
157 return false;
158 }
159 }
160 return true;
161 } else {
162 ANSR_LOGD("Single time reminder, not need to update next trigger time");
163 SetSnoozeTimesDynamic(GetSnoozeTimes());
164 SetExpired(true);
165 return false;
166 }
167 }
168
Marshalling(Parcel & parcel) const169 bool ReminderRequestAlarm::Marshalling(Parcel &parcel) const
170 {
171 if (ReminderRequest::Marshalling(parcel)) {
172 WRITE_UINT8_RETURN_FALSE_LOG(parcel, hour_, "hour");
173 WRITE_UINT8_RETURN_FALSE_LOG(parcel, minute_, "minute");
174 WRITE_UINT8_RETURN_FALSE_LOG(parcel, repeatDaysOfWeek_, "repeatDaysOfWeek");
175 return true;
176 }
177 return false;
178 }
179
Unmarshalling(Parcel & parcel)180 ReminderRequestAlarm *ReminderRequestAlarm::Unmarshalling(Parcel &parcel)
181 {
182 ANSR_LOGD("New alarm");
183 auto objptr = new (std::nothrow) ReminderRequestAlarm();
184 if (objptr == nullptr) {
185 ANSR_LOGE("Failed to create reminder alarm due to no memory.");
186 return objptr;
187 }
188 if (!objptr->ReadFromParcel(parcel)) {
189 delete objptr;
190 objptr = nullptr;
191 }
192 return objptr;
193 }
194
ReadFromParcel(Parcel & parcel)195 bool ReminderRequestAlarm::ReadFromParcel(Parcel &parcel)
196 {
197 if (ReminderRequest::ReadFromParcel(parcel)) {
198 READ_UINT8_RETURN_FALSE_LOG(parcel, hour_, "hour");
199 READ_UINT8_RETURN_FALSE_LOG(parcel, minute_, "minute");
200 READ_UINT8_RETURN_FALSE_LOG(parcel, repeatDaysOfWeek_, "repeatDaysOfWeek");
201
202 ANSR_LOGD("hour_=%{public}d, minute_=%{public}d", hour_, minute_);
203 return true;
204 }
205 return false;
206 }
207 }
208 }