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