• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-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_module.h"
17 #if (FEATURE_TIMER_MODULE == 1)
18 #include <cstdint>
19 #include <string.h>
20 #include "ace_log.h"
21 #include "ace_mem_base.h"
22 #ifdef TDD_ASSERTIONS
23 #include "async_task_manager.h"
24 #endif
25 #ifndef SYNC_TIMER_CALLBACK
26 #include "js_async_work.h"
27 #endif // TARGET_SIMULATOR
28 #include "js_fwk_common.h"
29 #include "nativeapi_timer_task.h"
30 
31 namespace OHOS {
32 namespace ACELite {
Init()33 void TimerModule::Init()
34 {
35     const char * const setTimeout = "setTimeout";
36     const char * const clearTimeout = "clearTimeout";
37     const char * const setInterval = "setInterval";
38     const char * const clearInterval = "clearInterval";
39     initRes_ = InitTimerTask();
40     if (initRes_ < 0) {
41         HILOG_ERROR(HILOG_MODULE_ACE, "init timer failed %{public}d", initRes_);
42     }
43     CreateNamedFunction(setTimeout, SetTimeout);
44     CreateNamedFunction(clearTimeout, ClearTimer);
45     CreateNamedFunction(setInterval, SetInterval);
46     CreateNamedFunction(clearInterval, ClearTimer);
47 }
48 
CreateTimer(const jerry_value_t func,const jerry_value_t context,const jerry_value_t * args,const jerry_length_t argsNum,bool repeated)49 jerry_value_t TimerModule::CreateTimer(const jerry_value_t func,
50                                        const jerry_value_t context,
51                                        const jerry_value_t *args,
52                                        const jerry_length_t argsNum,
53                                        bool repeated)
54 {
55     if (TimerModule::GetInstance()->GetInitState() < 0) {
56         HILOG_ERROR(HILOG_MODULE_ACE, "start timer failed, timer init failed %{public}d",
57                     TimerModule::GetInstance()->GetInitState());
58         return UNDEFINED;
59     }
60     const uint8_t leastArguments = 2;
61     if ((argsNum < leastArguments) || (GetInstance()->GetTimerList() == nullptr)) {
62         return UNDEFINED;
63     }
64     TimerList::Arguments *arguments = new TimerList::Arguments();
65     if (arguments == nullptr) {
66         return jerry_create_error(JERRY_ERROR_EVAL, reinterpret_cast<const jerry_char_t *>("memory error"));
67     }
68     arguments->context = context;
69     jerry_value_t function = args[0];
70     arguments->func = jerry_acquire_value(function);
71     arguments->repeated = repeated;
72     TimerList* timerList = GetInstance()->GetTimerList();
73     if (argsNum > leastArguments) {
74         uint8_t funcNumber = argsNum - leastArguments;
75         jerry_value_t *funcArg =
76             static_cast<jerry_value_t *>(ace_malloc(sizeof(jerry_value_t) * (funcNumber)));
77         if (funcArg == nullptr) {
78             timerList->ReleaseArguments(arguments);
79             return jerry_create_error(JERRY_ERROR_EVAL, reinterpret_cast<const jerry_char_t *>("memory error"));
80         }
81         for (uint8_t i = 0; i < funcNumber; i++) {
82             funcArg[i] = jerry_acquire_value(args[i + leastArguments]);
83         }
84         arguments->args = funcArg;
85         arguments->argsNum = funcNumber;
86     }
87     jerry_value_t retVal = StartTask(arguments, args[1], repeated);
88     if (jerry_value_is_undefined(retVal)) {
89         timerList->ReleaseArguments(arguments);
90     }
91     return retVal;
92 }
93 
StartTask(TimerList::Arguments * arguments,jerry_value_t time,bool repeated)94 jerry_value_t TimerModule::StartTask(TimerList::Arguments *arguments, jerry_value_t time, bool repeated)
95 {
96     timerHandle_t timerId = nullptr;
97     TimerList *timerList = GetInstance()->GetTimerList();
98     jerry_value_t retVal = UNDEFINED;
99     if (timerList == nullptr) {
100         return retVal;
101     }
102     if (!jerry_value_is_number(time)) {
103         retVal = timerList->AddTimer(timerId, arguments);
104         if (jerry_value_is_undefined(retVal)) {
105             return retVal;
106         }
107         Task(arguments);
108     } else {
109         jerry_value_t numProp = jerry_value_to_number(time);
110         int64_t num = (int64_t)(jerry_get_number_value(numProp));
111         jerry_release_value(numProp);
112         if (num <= 0 || num >= UINT32_MAX) {
113             retVal = timerList->AddTimer(timerId, arguments);
114             if (jerry_value_is_undefined(retVal)) {
115                 return retVal;
116             }
117             Task(arguments);
118         } else {
119             int result = StartTimerTask(repeated, (uint32_t)num, reinterpret_cast<void *>(Task), arguments, &timerId);
120             if (result < 0) {
121                 return UNDEFINED;
122             }
123             retVal = timerList->AddTimer(timerId, arguments);
124         }
125     }
126     return retVal;
127 }
128 
ClearTimer(const jerry_value_t func,const jerry_value_t context,const jerry_value_t * args,const jerry_length_t argsNum)129 jerry_value_t TimerModule::ClearTimer(const jerry_value_t func,
130                                       const jerry_value_t context,
131                                       const jerry_value_t *args,
132                                       const jerry_length_t argsNum)
133 {
134     if (TimerModule::GetInstance()->GetInitState() < 0) {
135         HILOG_ERROR(HILOG_MODULE_ACE, "stop timer failed, init timer failed %{public}d",
136                     TimerModule::GetInstance()->GetInitState());
137         return UNDEFINED;
138     }
139     if (argsNum == 0) {
140         return UNDEFINED;
141     }
142     TimerList* timerList = GetInstance()->GetTimerList();
143     if ((timerList != nullptr) && (jerry_value_is_number(args[0]))) {
144         int16_t timerKey = IntegerOf(args[0]);
145         if (timerKey < 0) {
146             return UNDEFINED;
147         }
148         uint8_t index = (uint8_t)(timerKey);
149         TimerList::TimerNode* timer = timerList->GetTimer(index);
150         if (timer != nullptr) {
151             int result = StopTimerTask(timer->timerId);
152             if (result >= 0) {
153                 timerList->DeleteTimer(index);
154             }
155         }
156     }
157     return UNDEFINED;
158 }
159 
Task(void * arguments)160 void TimerModule::Task(void *arguments)
161 {
162     TimerList::Arguments *arg = static_cast<TimerList::Arguments *>(arguments);
163     if (arg == nullptr) {
164         return;
165     }
166     TimerList *timerList = GetInstance()->GetTimerList();
167     if (timerList == nullptr) {
168         return;
169     }
170 #ifndef SYNC_TIMER_CALLBACK
171     uint8_t* index = static_cast<uint8_t*>(ace_malloc(sizeof(uint8_t)));
172     bool check = true;
173     if (index == nullptr) {
174         check = false;
175         HILOG_ERROR(HILOG_MODULE_ACE, "copy timer id failed\n");
176     } else {
177         *index = arg->index;
178 #ifdef TDD_ASSERTIONS
179         if (DISPATCH_FAILURE == AsyncTaskManager::GetInstance().Dispatch(TimerModule::Execute, index)) {
180 #else
181         if (!JsAsyncWork::DispatchAsyncWork(TimerModule::Execute, index)) {
182 #endif
183             ACE_FREE(index);
184             check = false;
185         }
186     }
187     if (!check && (!arg->repeated)) {
188 #if defined(__LITEOS__)
189         TimerList::TimerNode* timer = timerList->GetTimer(arg->index);
190         if (timer != nullptr) {
191             StopTimerTask(timer->timerId);
192         }
193 #endif
194         timerList->DeleteTimer(arg->index);
195     }
196 #else // SYNC_TIMER_CALLBACK
197     if (jerry_value_is_function(arg->func)) {
198         CallJSFunctionAutoRelease(arg->func, arg->context, arg->args, arg->argsNum);
199     }
200     if (!arg->repeated) {
201         timerList->DeleteTimer(arg->index);
202     }
203 #endif // SYNC_TIMER_CALLBACK
204 }
205 
206 #ifndef SYNC_TIMER_CALLBACK
207 void TimerModule::Execute(void *data)
208 {
209     uint8_t* timerId = static_cast<uint8_t*>(data);
210     if (timerId == nullptr) {
211         HILOG_ERROR(HILOG_MODULE_ACE, "timer index is invalid");
212         return;
213     }
214     TimerList* timerList = GetInstance()->GetTimerList();
215     if (timerList != nullptr) {
216         TimerList::TimerNode* timer = timerList->GetTimer(*timerId);
217         if (timer != nullptr) {
218             TimerList::Arguments* funcArgs = timer->arguments;
219             if (jerry_value_is_function(funcArgs->func)) {
220                 CallJSFunctionAutoRelease(funcArgs->func, funcArgs->context, funcArgs->args, funcArgs->argsNum);
221             }
222             // if timer is once, release the arguments
223             // check the timer node is release or not
224             TimerList::TimerNode* currentTimer = timerList->GetTimer(*timerId);
225             if ((currentTimer != nullptr) && (!funcArgs->repeated)) {
226 #if defined(__LITEOS__)
227                 StopTimerTask(timer->timerId);
228 #endif
229                 timerList->DeleteTimer(funcArgs->index);
230             }
231         }
232     }
233     ACE_FREE(timerId);
234 }
235 #endif // TARGET_SIMULATOR
236 } // namespace ACELite
237 } // namespace OHOS
238 #endif // FEATURE_TIMER_MODULE
239