1/*
2 * Copyright (C) 2021 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 "timer_info.h"
17
18#include <cinttypes>
19
20#include "time_hilog.h"
21
22namespace OHOS {
23namespace MiscServices {
24bool TimerInfo::operator==(const TimerInfo &other) const
25{
26    return this->id == other.id;
27}
28
29bool TimerInfo::Matches(const std::string &packageName) const
30{
31    return false;
32}
33
34TimerInfo::TimerInfo(uint64_t _id, int _type,
35                     std::chrono::milliseconds _when,
36                     std::chrono::steady_clock::time_point _whenElapsed,
37                     std::chrono::milliseconds _windowLength,
38                     std::chrono::steady_clock::time_point _maxWhen,
39                     std::chrono::milliseconds _interval,
40                     std::function<int32_t (const uint64_t)> _callback,
41                     std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> _wantAgent,
42                     uint32_t _flags,
43                     int _uid,
44                     int _pid,
45                     const std::string &_bundleName)
46    : id {_id},
47      type {_type},
48      origWhen {_when},
49      wakeup {_type == ITimerManager::ELAPSED_REALTIME_WAKEUP || _type == ITimerManager::RTC_WAKEUP},
50      callback {std::move(_callback)},
51      wantAgent {_wantAgent},
52      flags {_flags},
53      uid {_uid},
54      pid {_pid},
55      when {_when},
56      windowLength {_windowLength},
57      whenElapsed {_whenElapsed},
58      maxWhenElapsed {_maxWhen},
59      repeatInterval {_interval},
60      bundleName {_bundleName}
61{
62    originWhenElapsed = _whenElapsed;
63    originMaxWhenElapsed = _maxWhen;
64}
65
66/* Please make sure that the first param is current boottime */
67bool TimerInfo::UpdateWhenElapsedFromNow(std::chrono::steady_clock::time_point now, std::chrono::nanoseconds offset)
68{
69    TIME_HILOGD(TIME_MODULE_SERVICE, "Update whenElapsed, id=%{public}" PRId64 "", id);
70    auto oldWhenElapsed = whenElapsed;
71    whenElapsed = now + offset;
72    auto oldMaxWhenElapsed = maxWhenElapsed;
73    maxWhenElapsed = whenElapsed + windowLength;
74    std::chrono::milliseconds currentTime;
75    if (type == ITimerManager::RTC || type == ITimerManager::RTC_WAKEUP) {
76        currentTime =
77            std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
78    } else {
79        currentTime = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
80    }
81    auto offsetMill = std::chrono::duration_cast<std::chrono::milliseconds>(offset);
82    when = currentTime + offsetMill;
83    return (oldWhenElapsed != whenElapsed) || (oldMaxWhenElapsed != maxWhenElapsed);
84}
85
86bool TimerInfo::AdjustTimer(const std::chrono::steady_clock::time_point &now, const uint32_t interval)
87{
88    auto oldWhenElapsed = whenElapsed;
89    auto oldMaxWhenElapsed = maxWhenElapsed;
90    std::chrono::duration<int, std::ratio<1, HALF_SECEND>> halfIntervalSec(interval);
91    std::chrono::duration<int, std::ratio<1, 1>> intervalSec(interval);
92    auto oldTimeSec = std::chrono::duration_cast<std::chrono::seconds>(whenElapsed.time_since_epoch());
93    auto timeSec = ((oldTimeSec + halfIntervalSec) / intervalSec) * intervalSec;
94    whenElapsed = std::chrono::steady_clock::time_point(timeSec);
95    if (windowLength == std::chrono::milliseconds::zero()) {
96        maxWhenElapsed = whenElapsed;
97    } else {
98        auto oldMaxTimeSec = std::chrono::duration_cast<std::chrono::seconds>(maxWhenElapsed.time_since_epoch());
99        auto maxTimeSec = ((oldMaxTimeSec + halfIntervalSec) / intervalSec) * intervalSec;
100        maxWhenElapsed = std::chrono::steady_clock::time_point(maxTimeSec);
101    }
102    if (whenElapsed < now) {
103        whenElapsed += std::chrono::duration_cast<std::chrono::milliseconds>(intervalSec);
104    }
105    if (maxWhenElapsed < now) {
106        maxWhenElapsed += std::chrono::duration_cast<std::chrono::milliseconds>(intervalSec);
107    }
108    auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(
109        whenElapsed.time_since_epoch() - oldWhenElapsed.time_since_epoch());
110    when = when + delta;
111    return (oldWhenElapsed != whenElapsed) || (oldMaxWhenElapsed != maxWhenElapsed);
112}
113
114bool TimerInfo::RestoreAdjustTimer()
115{
116    auto oldWhenElapsed = whenElapsed;
117    auto oldMaxWhenElapsed = maxWhenElapsed;
118    whenElapsed = originWhenElapsed;
119    maxWhenElapsed = originMaxWhenElapsed;
120    auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(
121        whenElapsed.time_since_epoch() - oldWhenElapsed.time_since_epoch());
122    when = when + delta;
123    return (oldWhenElapsed != whenElapsed) || (oldMaxWhenElapsed != maxWhenElapsed);
124}
125} // MiscServices
126} // OHOS