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 #include <cmath>
22 
23 #include "common_timer_errors.h"
24 #include "matching_skills.h"
25 #include "time_common.h"
26 #include "time_service_notify.h"
27 #include "time_system_ability.h"
28 #include "timer_manager_interface.h"
29 
30 using namespace std::chrono;
31 
32 namespace OHOS {
33 namespace MiscServices {
34 namespace {
35 constexpr uint64_t MINUTE_TO_MILLISECOND = 60000;
36 constexpr uint64_t SECOND_TO_MILLISECOND = 1000;
37 constexpr int64_t SECOND_TO_NANO = 1000000000;
38 } // namespace
39 
GetInstance()40 TimeTickNotify &TimeTickNotify::GetInstance()
41 {
42     static TimeTickNotify instance;
43     return instance;
44 }
45 
46 TimeTickNotify::TimeTickNotify() = default;
47 TimeTickNotify::~TimeTickNotify() = default;
48 
Init()49 void TimeTickNotify::Init()
50 {
51     TIME_HILOGD(TIME_MODULE_SERVICE, "Tick notify start.");
52     TimerPara timerPara{};
53     timerPara.timerType = static_cast<int>(ITimerManager::TimerType::RTC);
54     timerPara.windowLength = 0;
55     timerPara.interval = 0;
56     timerPara.flag = 0;
57     auto callback = [this](uint64_t id) -> int32_t {
58         this->Callback();
59         return E_TIME_OK;
60     };
61     std::lock_guard<std::mutex> lock(timeridMutex_);
62     TimeSystemAbility::GetInstance()->CreateTimer(timerPara, callback, timerId_);
63     auto trigger = RefreshNextTriggerTime();
64     TimeSystemAbility::GetInstance()->StartTimer(timerId_, trigger.first);
65     TIME_HILOGI(TIME_MODULE_SERVICE, "Tick timer timerId: %{public}" PRIu64 "", timerId_);
66 }
67 
Callback()68 void TimeTickNotify::Callback()
69 {
70     std::lock_guard<std::mutex> lock(timeridMutex_);
71     auto trigger = RefreshNextTriggerTime();
72     TimeSystemAbility::GetInstance()->StartTimer(timerId_, trigger.first);
73     if (trigger.second) {
74         auto currentTime = steady_clock::now().time_since_epoch().count();
75         if (std::abs(currentTime - lastTriggerTime_) > SECOND_TO_NANO) {
76             TimeServiceNotify::GetInstance().PublishTimeTickEvents(currentTime);
77             lastTriggerTime_ = currentTime;
78         }
79     }
80     TIME_HILOGI(TIME_MODULE_SERVICE, "id: %{public}" PRIu64 "", timerId_);
81 }
82 
RefreshNextTriggerTime()83 std::pair<uint64_t, bool> TimeTickNotify::RefreshNextTriggerTime()
84 {
85     int64_t time = 0;
86     TimeUtils::GetWallTimeMs(time);
87     uint64_t currTime = static_cast<uint64_t>(time);
88     uint64_t timeMilliseconds = currTime % MINUTE_TO_MILLISECOND;
89     bool isFirstSecond = timeMilliseconds < SECOND_TO_MILLISECOND;
90     uint64_t nextTriggerTime = ((currTime / MINUTE_TO_MILLISECOND) + 1) * MINUTE_TO_MILLISECOND;
91     return std::make_pair(nextTriggerTime, isFirstSecond);
92 }
93 
Stop()94 void TimeTickNotify::Stop()
95 {
96     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
97     TimeSystemAbility::GetInstance()->DestroyTimer(timerId_, false);
98     TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
99 }
100 } // namespace MiscServices
101 } // namespace OHOS