1cf69771bSopenharmony_ci/*
2cf69771bSopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd.
3cf69771bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4cf69771bSopenharmony_ci * you may not use this file except in compliance with the License.
5cf69771bSopenharmony_ci * You may obtain a copy of the License at
6cf69771bSopenharmony_ci *
7cf69771bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8cf69771bSopenharmony_ci *
9cf69771bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10cf69771bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11cf69771bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12cf69771bSopenharmony_ci * See the License for the specific language governing permissions and
13cf69771bSopenharmony_ci * limitations under the License.
14cf69771bSopenharmony_ci */
15cf69771bSopenharmony_ci#include "time_tick_notify.h"
16cf69771bSopenharmony_ci
17cf69771bSopenharmony_ci#include <chrono>
18cf69771bSopenharmony_ci#include <cinttypes>
19cf69771bSopenharmony_ci#include <ctime>
20cf69771bSopenharmony_ci#include <thread>
21cf69771bSopenharmony_ci
22cf69771bSopenharmony_ci#include "common_timer_errors.h"
23cf69771bSopenharmony_ci#include "matching_skills.h"
24cf69771bSopenharmony_ci#include "time_common.h"
25cf69771bSopenharmony_ci#include "time_service_notify.h"
26cf69771bSopenharmony_ci#include "time_system_ability.h"
27cf69771bSopenharmony_ci#include "timer_manager_interface.h"
28cf69771bSopenharmony_ci
29cf69771bSopenharmony_ciusing namespace std::chrono;
30cf69771bSopenharmony_ci
31cf69771bSopenharmony_cinamespace OHOS {
32cf69771bSopenharmony_cinamespace MiscServices {
33cf69771bSopenharmony_cinamespace {
34cf69771bSopenharmony_ciconstexpr uint64_t MINUTE_TO_MILLISECOND = 60000;
35cf69771bSopenharmony_ciconstexpr uint64_t MICRO_TO_MILLISECOND = 1000;
36cf69771bSopenharmony_ciconstexpr uint64_t MILLISECOND_TO_SECOND = 1000;
37cf69771bSopenharmony_ci} // namespace
38cf69771bSopenharmony_ci
39cf69771bSopenharmony_ciTimeTickNotify &TimeTickNotify::GetInstance()
40cf69771bSopenharmony_ci{
41cf69771bSopenharmony_ci    static TimeTickNotify instance;
42cf69771bSopenharmony_ci    return instance;
43cf69771bSopenharmony_ci}
44cf69771bSopenharmony_ci
45cf69771bSopenharmony_ciTimeTickNotify::TimeTickNotify() : timer_("TickTimer"){};
46cf69771bSopenharmony_ciTimeTickNotify::~TimeTickNotify() = default;
47cf69771bSopenharmony_ci
48cf69771bSopenharmony_civoid TimeTickNotify::Init()
49cf69771bSopenharmony_ci{
50cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "Tick notify start.");
51cf69771bSopenharmony_ci    uint32_t ret = timer_.Setup();
52cf69771bSopenharmony_ci    if (ret != Utils::TIMER_ERR_OK) {
53cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "Timer Setup failed: %{public}d", ret);
54cf69771bSopenharmony_ci        return;
55cf69771bSopenharmony_ci    }
56cf69771bSopenharmony_ci    auto callback = [this]() { this->Callback(); };
57cf69771bSopenharmony_ci    uint64_t nextTriggerTime = RefreshNextTriggerTime();
58cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "Tick notify triggertime: %{public}" PRId64 "", nextTriggerTime);
59cf69771bSopenharmony_ci    std::lock_guard<std::mutex> lock(timeridMutex_);
60cf69771bSopenharmony_ci    timerId_ = timer_.Register(callback, nextTriggerTime);
61cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "Tick timer ID: %{public}d", timerId_);
62cf69771bSopenharmony_ci}
63cf69771bSopenharmony_ci
64cf69771bSopenharmony_civoid TimeTickNotify::Callback()
65cf69771bSopenharmony_ci{
66cf69771bSopenharmony_ci    std::lock_guard<std::mutex> lock(timeridMutex_);
67cf69771bSopenharmony_ci    timer_.Unregister(timerId_);
68cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "Unregister id: %{public}d", timerId_);
69cf69771bSopenharmony_ci    uint64_t nextTriggerTime = RefreshNextTriggerTime();
70cf69771bSopenharmony_ci    auto callback = [this]() { this->Callback(); };
71cf69771bSopenharmony_ci    timerId_ = timer_.Register(callback, nextTriggerTime, true);
72cf69771bSopenharmony_ci    if (nextTriggerTime > (MINUTE_TO_MILLISECOND - MILLISECOND_TO_SECOND)) {
73cf69771bSopenharmony_ci        auto currentTime = steady_clock::now().time_since_epoch().count();
74cf69771bSopenharmony_ci        TimeServiceNotify::GetInstance().PublishTimeTickEvents(currentTime);
75cf69771bSopenharmony_ci    }
76cf69771bSopenharmony_ci    TIME_HILOGI(TIME_MODULE_SERVICE, "id: %{public}d triggertime: %{public}" PRId64 "", timerId_, nextTriggerTime);
77cf69771bSopenharmony_ci}
78cf69771bSopenharmony_ci
79cf69771bSopenharmony_civoid TimeTickNotify::PowerCallback()
80cf69771bSopenharmony_ci{
81cf69771bSopenharmony_ci    std::lock_guard<std::mutex> lock(timeridMutex_);
82cf69771bSopenharmony_ci    timer_.Unregister(timerId_);
83cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "Unregister id: %{public}d", timerId_);
84cf69771bSopenharmony_ci    uint64_t nextTriggerTime = RefreshNextTriggerTime();
85cf69771bSopenharmony_ci    auto callback = [this]() { this->Callback(); };
86cf69771bSopenharmony_ci    timerId_ = timer_.Register(callback, nextTriggerTime, true);
87cf69771bSopenharmony_ci    TIME_HILOGI(TIME_MODULE_SERVICE, "id: %{public}d triggertime: %{public}" PRId64 "", timerId_, nextTriggerTime);
88cf69771bSopenharmony_ci}
89cf69771bSopenharmony_ci
90cf69771bSopenharmony_ciuint64_t TimeTickNotify::RefreshNextTriggerTime()
91cf69771bSopenharmony_ci{
92cf69771bSopenharmony_ci    auto UTCTimeMicro = static_cast<uint64_t>(duration_cast<microseconds>(system_clock::now()
93cf69771bSopenharmony_ci        .time_since_epoch()).count());
94cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "Time micro: %{public}" PRIu64 "", UTCTimeMicro);
95cf69771bSopenharmony_ci    uint64_t timeMilliseconds = (UTCTimeMicro / MICRO_TO_MILLISECOND) % MINUTE_TO_MILLISECOND;
96cf69771bSopenharmony_ci    uint64_t nextTriggerTime = MINUTE_TO_MILLISECOND - timeMilliseconds;
97cf69771bSopenharmony_ci    return nextTriggerTime;
98cf69771bSopenharmony_ci}
99cf69771bSopenharmony_ci
100cf69771bSopenharmony_civoid TimeTickNotify::Stop()
101cf69771bSopenharmony_ci{
102cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
103cf69771bSopenharmony_ci    timer_.Shutdown();
104cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
105cf69771bSopenharmony_ci}
106cf69771bSopenharmony_ci} // namespace MiscServices
107cf69771bSopenharmony_ci} // namespace OHOS