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#include "time_tick_notify.h"
16
17#include <chrono>
18#include <cinttypes>
19#include <ctime>
20#include <thread>
21
22#include "common_timer_errors.h"
23#include "matching_skills.h"
24#include "time_common.h"
25#include "time_service_notify.h"
26#include "time_system_ability.h"
27#include "timer_manager_interface.h"
28
29using namespace std::chrono;
30
31namespace OHOS {
32namespace MiscServices {
33namespace {
34constexpr uint64_t MINUTE_TO_MILLISECOND = 60000;
35constexpr uint64_t MICRO_TO_MILLISECOND = 1000;
36constexpr uint64_t MILLISECOND_TO_SECOND = 1000;
37} // namespace
38
39TimeTickNotify &TimeTickNotify::GetInstance()
40{
41    static TimeTickNotify instance;
42    return instance;
43}
44
45TimeTickNotify::TimeTickNotify() : timer_("TickTimer"){};
46TimeTickNotify::~TimeTickNotify() = default;
47
48void TimeTickNotify::Init()
49{
50    TIME_HILOGD(TIME_MODULE_SERVICE, "Tick notify start.");
51    uint32_t ret = timer_.Setup();
52    if (ret != Utils::TIMER_ERR_OK) {
53        TIME_HILOGE(TIME_MODULE_SERVICE, "Timer Setup failed: %{public}d", ret);
54        return;
55    }
56    auto callback = [this]() { this->Callback(); };
57    uint64_t nextTriggerTime = RefreshNextTriggerTime();
58    TIME_HILOGD(TIME_MODULE_SERVICE, "Tick notify triggertime: %{public}" PRId64 "", nextTriggerTime);
59    std::lock_guard<std::mutex> lock(timeridMutex_);
60    timerId_ = timer_.Register(callback, nextTriggerTime);
61    TIME_HILOGD(TIME_MODULE_SERVICE, "Tick timer ID: %{public}d", timerId_);
62}
63
64void TimeTickNotify::Callback()
65{
66    std::lock_guard<std::mutex> lock(timeridMutex_);
67    timer_.Unregister(timerId_);
68    TIME_HILOGD(TIME_MODULE_SERVICE, "Unregister id: %{public}d", timerId_);
69    uint64_t nextTriggerTime = RefreshNextTriggerTime();
70    auto callback = [this]() { this->Callback(); };
71    timerId_ = timer_.Register(callback, nextTriggerTime, true);
72    if (nextTriggerTime > (MINUTE_TO_MILLISECOND - MILLISECOND_TO_SECOND)) {
73        auto currentTime = steady_clock::now().time_since_epoch().count();
74        TimeServiceNotify::GetInstance().PublishTimeTickEvents(currentTime);
75    }
76    TIME_HILOGI(TIME_MODULE_SERVICE, "id: %{public}d triggertime: %{public}" PRId64 "", timerId_, nextTriggerTime);
77}
78
79void TimeTickNotify::PowerCallback()
80{
81    std::lock_guard<std::mutex> lock(timeridMutex_);
82    timer_.Unregister(timerId_);
83    TIME_HILOGD(TIME_MODULE_SERVICE, "Unregister id: %{public}d", timerId_);
84    uint64_t nextTriggerTime = RefreshNextTriggerTime();
85    auto callback = [this]() { this->Callback(); };
86    timerId_ = timer_.Register(callback, nextTriggerTime, true);
87    TIME_HILOGI(TIME_MODULE_SERVICE, "id: %{public}d triggertime: %{public}" PRId64 "", timerId_, nextTriggerTime);
88}
89
90uint64_t TimeTickNotify::RefreshNextTriggerTime()
91{
92    auto UTCTimeMicro = static_cast<uint64_t>(duration_cast<microseconds>(system_clock::now()
93        .time_since_epoch()).count());
94    TIME_HILOGD(TIME_MODULE_SERVICE, "Time micro: %{public}" PRIu64 "", UTCTimeMicro);
95    uint64_t timeMilliseconds = (UTCTimeMicro / MICRO_TO_MILLISECOND) % MINUTE_TO_MILLISECOND;
96    uint64_t nextTriggerTime = MINUTE_TO_MILLISECOND - timeMilliseconds;
97    return nextTriggerTime;
98}
99
100void TimeTickNotify::Stop()
101{
102    TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
103    timer_.Shutdown();
104    TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
105}
106} // namespace MiscServices
107} // namespace OHOS