1cb69b360Sopenharmony_ci/*
2cb69b360Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3cb69b360Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4cb69b360Sopenharmony_ci * you may not use this file except in compliance with the License.
5cb69b360Sopenharmony_ci * You may obtain a copy of the License at
6cb69b360Sopenharmony_ci *
7cb69b360Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8cb69b360Sopenharmony_ci *
9cb69b360Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10cb69b360Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11cb69b360Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12cb69b360Sopenharmony_ci * See the License for the specific language governing permissions and
13cb69b360Sopenharmony_ci * limitations under the License.
14cb69b360Sopenharmony_ci */
15cb69b360Sopenharmony_ci
16cb69b360Sopenharmony_ci#include "power_mgr_timer_util.h"
17cb69b360Sopenharmony_ci
18cb69b360Sopenharmony_ci#include <common.h>
19cb69b360Sopenharmony_ci#include <errno.h>
20cb69b360Sopenharmony_ci#include <securec.h>
21cb69b360Sopenharmony_ci#include <signal.h>
22cb69b360Sopenharmony_ci#include <stdint.h>
23cb69b360Sopenharmony_ci#include <string.h>
24cb69b360Sopenharmony_ci
25cb69b360Sopenharmony_ci#include "hilog_wrapper.h"
26cb69b360Sopenharmony_ci#include "power_mgr_time_util.h"
27cb69b360Sopenharmony_ci
28cb69b360Sopenharmony_citypedef struct {
29cb69b360Sopenharmony_ci    PowerTimer timerId;
30cb69b360Sopenharmony_ci    BOOL isRunning;
31cb69b360Sopenharmony_ci    int64_t whenMsec;
32cb69b360Sopenharmony_ci    int64_t intervalMsec;
33cb69b360Sopenharmony_ci    PowerTimerCallback timerCb;
34cb69b360Sopenharmony_ci    void *data;
35cb69b360Sopenharmony_ci} PowerTimerInfo;
36cb69b360Sopenharmony_ci
37cb69b360Sopenharmony_cistatic inline PowerTimerInfo *GetPowerTimerInfo(PowerTimer *timer)
38cb69b360Sopenharmony_ci{
39cb69b360Sopenharmony_ci    return GET_OBJECT(timer, PowerTimerInfo, timerId);
40cb69b360Sopenharmony_ci}
41cb69b360Sopenharmony_ci
42cb69b360Sopenharmony_cistatic void SetTimeSpec(struct timespec *ts, int64_t msec)
43cb69b360Sopenharmony_ci{
44cb69b360Sopenharmony_ci    ts->tv_sec = MsecToSec(msec);
45cb69b360Sopenharmony_ci    msec -= SecToMsec(ts->tv_sec);
46cb69b360Sopenharmony_ci    ts->tv_nsec = MsecToNsec(msec);
47cb69b360Sopenharmony_ci}
48cb69b360Sopenharmony_ci
49cb69b360Sopenharmony_cistatic BOOL StartTimer(PowerTimer timer, int64_t whenMsec, int64_t intervalMsec)
50cb69b360Sopenharmony_ci{
51cb69b360Sopenharmony_ci    struct itimerspec ts;
52cb69b360Sopenharmony_ci    SetTimeSpec(&ts.it_value, whenMsec);
53cb69b360Sopenharmony_ci    SetTimeSpec(&ts.it_interval, intervalMsec);
54cb69b360Sopenharmony_ci    int32_t ret = timer_settime(timer, 0, &ts, NULL);
55cb69b360Sopenharmony_ci    if (ret < 0) {
56cb69b360Sopenharmony_ci        POWER_HILOGE("Failed to start timer");
57cb69b360Sopenharmony_ci        return FALSE;
58cb69b360Sopenharmony_ci    }
59cb69b360Sopenharmony_ci    return TRUE;
60cb69b360Sopenharmony_ci}
61cb69b360Sopenharmony_ci
62cb69b360Sopenharmony_cistatic void TimerHandle(union sigval v)
63cb69b360Sopenharmony_ci{
64cb69b360Sopenharmony_ci    PowerTimerInfo *info = (PowerTimerInfo *)v.sival_ptr;
65cb69b360Sopenharmony_ci    if (info == NULL) {
66cb69b360Sopenharmony_ci        POWER_HILOGE("Invalid timer info");
67cb69b360Sopenharmony_ci        return;
68cb69b360Sopenharmony_ci    }
69cb69b360Sopenharmony_ci    if (info->timerCb != NULL) {
70cb69b360Sopenharmony_ci        info->timerCb(info->data);
71cb69b360Sopenharmony_ci    }
72cb69b360Sopenharmony_ci}
73cb69b360Sopenharmony_ci
74cb69b360Sopenharmony_ciPowerTimer *PowerMgrCreateTimer(int64_t whenMsec, int64_t intervalMsec, PowerTimerCallback cb)
75cb69b360Sopenharmony_ci{
76cb69b360Sopenharmony_ci    PowerTimerInfo *info = (PowerTimerInfo *)malloc(sizeof(PowerTimerInfo));
77cb69b360Sopenharmony_ci    if (info == NULL) {
78cb69b360Sopenharmony_ci        POWER_HILOGE("Failed allocate timer info");
79cb69b360Sopenharmony_ci        return NULL;
80cb69b360Sopenharmony_ci    }
81cb69b360Sopenharmony_ci    (void)memset_s(info, sizeof(PowerTimerInfo), 0, sizeof(PowerTimerInfo));
82cb69b360Sopenharmony_ci    info->isRunning = FALSE;
83cb69b360Sopenharmony_ci    info->whenMsec = whenMsec;
84cb69b360Sopenharmony_ci    info->intervalMsec = intervalMsec;
85cb69b360Sopenharmony_ci    info->timerCb = cb;
86cb69b360Sopenharmony_ci
87cb69b360Sopenharmony_ci    struct sigevent evp;
88cb69b360Sopenharmony_ci    (void)memset_s(&evp, sizeof(evp), 0, sizeof(evp));
89cb69b360Sopenharmony_ci    evp.sigev_value.sival_ptr = info;
90cb69b360Sopenharmony_ci    evp.sigev_notify = SIGEV_THREAD;
91cb69b360Sopenharmony_ci    evp.sigev_notify_function = TimerHandle;
92cb69b360Sopenharmony_ci    int32_t ret = timer_create(CLOCK_REALTIME, &evp, &info->timerId);
93cb69b360Sopenharmony_ci    if (ret < 0) {
94cb69b360Sopenharmony_ci        POWER_HILOGE("Failed to create timer");
95cb69b360Sopenharmony_ci        free(info);
96cb69b360Sopenharmony_ci        return NULL;
97cb69b360Sopenharmony_ci    }
98cb69b360Sopenharmony_ci    POWER_HILOGD("Succeed to create timer, id: %p", info->timerId);
99cb69b360Sopenharmony_ci
100cb69b360Sopenharmony_ci    return &info->timerId;
101cb69b360Sopenharmony_ci}
102cb69b360Sopenharmony_ci
103cb69b360Sopenharmony_ciBOOL PowerMgrResetTimer(PowerTimer *timer, int64_t whenMsec, int64_t intervalMsec)
104cb69b360Sopenharmony_ci{
105cb69b360Sopenharmony_ci    if (timer == NULL) {
106cb69b360Sopenharmony_ci        POWER_HILOGE("Invalid timer");
107cb69b360Sopenharmony_ci        return FALSE;
108cb69b360Sopenharmony_ci    }
109cb69b360Sopenharmony_ci    PowerMgrStopTimer(timer);
110cb69b360Sopenharmony_ci    PowerTimerInfo *info = GetPowerTimerInfo(timer);
111cb69b360Sopenharmony_ci    info->whenMsec = whenMsec;
112cb69b360Sopenharmony_ci    info->intervalMsec = intervalMsec;
113cb69b360Sopenharmony_ci    return TRUE;
114cb69b360Sopenharmony_ci}
115cb69b360Sopenharmony_ci
116cb69b360Sopenharmony_ciBOOL PowerMgrStartTimer(PowerTimer *timer, void *privateData)
117cb69b360Sopenharmony_ci{
118cb69b360Sopenharmony_ci    if (timer == NULL) {
119cb69b360Sopenharmony_ci        POWER_HILOGE("Invalid timer");
120cb69b360Sopenharmony_ci        return FALSE;
121cb69b360Sopenharmony_ci    }
122cb69b360Sopenharmony_ci
123cb69b360Sopenharmony_ci    PowerTimerInfo *info = GetPowerTimerInfo(timer);
124cb69b360Sopenharmony_ci    info->data = privateData;
125cb69b360Sopenharmony_ci    info->isRunning = TRUE;
126cb69b360Sopenharmony_ci    return StartTimer(info->timerId, info->whenMsec, info->intervalMsec);
127cb69b360Sopenharmony_ci}
128cb69b360Sopenharmony_ci
129cb69b360Sopenharmony_ciBOOL PowerMgrRestartTimer(PowerTimer *timer, void *privateData)
130cb69b360Sopenharmony_ci{
131cb69b360Sopenharmony_ci    if (timer == NULL) {
132cb69b360Sopenharmony_ci        POWER_HILOGE("Invalid timer");
133cb69b360Sopenharmony_ci        return FALSE;
134cb69b360Sopenharmony_ci    }
135cb69b360Sopenharmony_ci
136cb69b360Sopenharmony_ci    return PowerMgrStartTimer(timer, privateData);
137cb69b360Sopenharmony_ci}
138cb69b360Sopenharmony_ci
139cb69b360Sopenharmony_ciBOOL PowerMgrStopTimer(PowerTimer *timer)
140cb69b360Sopenharmony_ci{
141cb69b360Sopenharmony_ci    if (timer == NULL) {
142cb69b360Sopenharmony_ci        POWER_HILOGE("Invalid timer");
143cb69b360Sopenharmony_ci        return FALSE;
144cb69b360Sopenharmony_ci    }
145cb69b360Sopenharmony_ci
146cb69b360Sopenharmony_ci    PowerTimerInfo *info = GetPowerTimerInfo(timer);
147cb69b360Sopenharmony_ci    info->isRunning = FALSE;
148cb69b360Sopenharmony_ci    return StartTimer(info->timerId, 0, 0);
149cb69b360Sopenharmony_ci}
150cb69b360Sopenharmony_ci
151cb69b360Sopenharmony_civoid PowerMgrDestroyTimer(PowerTimer *timer)
152cb69b360Sopenharmony_ci{
153cb69b360Sopenharmony_ci    if (timer == NULL) {
154cb69b360Sopenharmony_ci        POWER_HILOGE("Invalid timer");
155cb69b360Sopenharmony_ci        return;
156cb69b360Sopenharmony_ci    }
157cb69b360Sopenharmony_ci
158cb69b360Sopenharmony_ci    PowerTimerInfo *info = GetPowerTimerInfo(timer);
159cb69b360Sopenharmony_ci    int32_t ret = timer_delete(info->timerId);
160cb69b360Sopenharmony_ci    POWER_HILOGD("Destory timer: %d", ret);
161cb69b360Sopenharmony_ci    free(info);
162cb69b360Sopenharmony_ci}
163