• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "js_timer.h"
17 
18 #include <atomic>
19 #include <string>
20 #include <vector>
21 
22 #include "hilog_wrapper.h"
23 #include "js_runtime.h"
24 #include "js_runtime_utils.h"
25 
26 #ifdef SUPPORT_GRAPHICS
27 #include "core/common/container_scope.h"
28 #endif
29 #ifdef ENABLE_HITRACE
30 #include "hitrace/trace.h"
31 #endif
32 
33 #ifdef SUPPORT_GRAPHICS
34 using OHOS::Ace::ContainerScope;
35 #endif
36 
37 namespace OHOS {
38 namespace AbilityRuntime {
39 namespace {
40 std::atomic<uint32_t> g_callbackId(1);
41 
42 class TraceIdScope final {
43 public:
TraceIdScope(const OHOS::HiviewDFX::HiTraceId & traceId)44     explicit TraceIdScope(const OHOS::HiviewDFX::HiTraceId& traceId) : valid_(traceId.IsValid())
45     {
46         if (valid_) {
47             OHOS::HiviewDFX::HiTraceChain::SetId(traceId);
48         }
49     }
50 
~TraceIdScope()51     ~TraceIdScope()
52     {
53         if (valid_) {
54             OHOS::HiviewDFX::HiTraceChain::ClearId();
55         }
56     }
57 
58     TraceIdScope(const TraceIdScope&) = delete;
59     TraceIdScope(TraceIdScope&&) = delete;
60     TraceIdScope& operator=(const TraceIdScope&) = delete;
61     TraceIdScope& operator=(TraceIdScope&&) = delete;
62 
63 private:
64     bool valid_ = false;
65 };
66 
67 class JsTimer final {
68 public:
JsTimer(JsRuntime & jsRuntime,const std::shared_ptr<NativeReference> & jsFunction,const std::string & name,int64_t interval,bool isInterval)69     JsTimer(JsRuntime& jsRuntime, const std::shared_ptr<NativeReference>& jsFunction, const std::string &name,
70         int64_t interval, bool isInterval)
71         : jsRuntime_(jsRuntime), jsFunction_(jsFunction), name_(name), interval_(interval), isInterval_(isInterval)
72     {}
73 
74     ~JsTimer() = default;
75 
operator ()() const76     void operator()() const
77     {
78         if (isInterval_) {
79             jsRuntime_.PostTask(*this, name_, interval_);
80         }
81 #ifdef SUPPORT_GRAPHICS
82         // call js function
83         ContainerScope containerScope(containerScopeId_);
84 #endif
85         HandleScope handleScope(jsRuntime_);
86 
87         std::vector<NativeValue*> args_;
88         args_.reserve(jsArgs_.size());
89         for (auto arg : jsArgs_) {
90             args_.emplace_back(arg->Get());
91         }
92 
93 #ifdef ENABLE_HITRACE
94         TraceIdScope traceIdScope(traceId_);
95 #endif
96         NativeEngine& engine = jsRuntime_.GetNativeEngine();
97         engine.CallFunction(engine.CreateUndefined(), jsFunction_->Get(), args_.data(), args_.size());
98     }
99 
PushArgs(const std::shared_ptr<NativeReference> & ref)100     void PushArgs(const std::shared_ptr<NativeReference>& ref)
101     {
102         jsArgs_.emplace_back(ref);
103     }
104 
105 private:
106     JsRuntime& jsRuntime_;
107     std::shared_ptr<NativeReference> jsFunction_;
108     std::vector<std::shared_ptr<NativeReference>> jsArgs_;
109     std::string name_;
110     int64_t interval_ = 0;
111     bool isInterval_ = false;
112 #ifdef SUPPORT_GRAPHICS
113     int32_t containerScopeId_ = ContainerScope::CurrentId();
114 #endif
115 #ifdef ENABLE_HITRACE
116     OHOS::HiviewDFX::HiTraceId traceId_ = OHOS::HiviewDFX::HiTraceChain::GetId();
117 #endif
118 };
119 
StartTimeoutOrInterval(NativeEngine * engine,NativeCallbackInfo * info,bool isInterval)120 NativeValue* StartTimeoutOrInterval(NativeEngine* engine, NativeCallbackInfo* info, bool isInterval)
121 {
122     if (engine == nullptr || info == nullptr) {
123         HILOG_ERROR("StartTimeoutOrInterval, engine or callback info is nullptr.");
124         return nullptr;
125     }
126 
127     // parameter check, must have at least 2 params
128     if (info->argc < 2 || info->argv[0]->TypeOf() != NATIVE_FUNCTION || info->argv[1]->TypeOf() != NATIVE_NUMBER) {
129         HILOG_ERROR("Set callback timer failed with invalid parameter.");
130         return engine->CreateUndefined();
131     }
132 
133     // parse parameter
134     std::shared_ptr<NativeReference> jsFunction(engine->CreateReference(info->argv[0], 1));
135     int64_t delayTime = *ConvertNativeValueTo<NativeNumber>(info->argv[1]);
136     uint32_t callbackId = g_callbackId.fetch_add(1, std::memory_order_relaxed);
137     std::string name = "JsRuntimeTimer_";
138     name.append(std::to_string(callbackId));
139 
140     // create timer task
141     JsRuntime& jsRuntime = *reinterpret_cast<JsRuntime*>(engine->GetJsEngine());
142     JsTimer task(jsRuntime, jsFunction, name, delayTime, isInterval);
143     for (size_t index = 2; index < info->argc; ++index) {
144         task.PushArgs(std::shared_ptr<NativeReference>(engine->CreateReference(info->argv[index], 1)));
145     }
146 
147     jsRuntime.PostTask(task, name, delayTime);
148     return engine->CreateNumber(callbackId);
149 }
150 
StartTimeout(NativeEngine * engine,NativeCallbackInfo * info)151 NativeValue* StartTimeout(NativeEngine* engine, NativeCallbackInfo* info)
152 {
153     return StartTimeoutOrInterval(engine, info, false);
154 }
155 
StartInterval(NativeEngine * engine,NativeCallbackInfo * info)156 NativeValue* StartInterval(NativeEngine* engine, NativeCallbackInfo* info)
157 {
158     return StartTimeoutOrInterval(engine, info, true);
159 }
160 
StopTimeoutOrInterval(NativeEngine * engine,NativeCallbackInfo * info)161 NativeValue* StopTimeoutOrInterval(NativeEngine* engine, NativeCallbackInfo* info)
162 {
163     if (engine == nullptr || info == nullptr) {
164         HILOG_ERROR("Stop timeout or interval failed with engine or callback info is nullptr.");
165         return nullptr;
166     }
167 
168     // parameter check, must have at least 1 param
169     if (info->argc < 1 || info->argv[0]->TypeOf() != NATIVE_NUMBER) {
170         HILOG_ERROR("Clear callback timer failed with invalid parameter.");
171         return engine->CreateUndefined();
172     }
173 
174     uint32_t callbackId = *ConvertNativeValueTo<NativeNumber>(info->argv[0]);
175     std::string name = "JsRuntimeTimer_";
176     name.append(std::to_string(callbackId));
177 
178     // event should be cancelable before executed
179     JsRuntime& jsRuntime = *reinterpret_cast<JsRuntime*>(engine->GetJsEngine());
180     jsRuntime.RemoveTask(name);
181     return engine->CreateUndefined();
182 }
183 }
184 
InitTimerModule(NativeEngine & engine,NativeObject & globalObject)185 void InitTimerModule(NativeEngine& engine, NativeObject& globalObject)
186 {
187     HILOG_DEBUG("InitTimerModule begin.");
188     const char *moduleName = "JsTimer";
189     BindNativeFunction(engine, globalObject, "setTimeout", moduleName, StartTimeout);
190     BindNativeFunction(engine, globalObject, "setInterval", moduleName, StartInterval);
191     BindNativeFunction(engine, globalObject, "clearTimeout", moduleName, StopTimeoutOrInterval);
192     BindNativeFunction(engine, globalObject, "clearInterval", moduleName, StopTimeoutOrInterval);
193 }
194 } // namespace AbilityRuntime
195 } // namespace OHOS