1 /*
2 * Copyright (C) 2023 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 <cstdio>
17 #include <functional>
18 #include <string>
19
20 #include "base/perfmonitor/perf_monitor.h"
21 #include "napi_perf_monitor.h"
22
23 namespace OHOS::Ace::Napi {
24 static constexpr uint32_t LAST_DOWN = 0;
25 static constexpr uint32_t LAST_UP = 1;
26 static constexpr uint32_t FIRST_MOVE = 2;
27 static constexpr uint32_t PERF_TOUCH_EVENT = 0;
28 static constexpr uint32_t PERF_MOUSE_EVENT = 1;
29 static constexpr uint32_t PERF_TOUCHPAD_EVENT = 2;
30 static constexpr uint32_t PERF_JOYSTICK_EVENT = 3;
31 static constexpr uint32_t PERF_KEY_EVENT = 4;
32 constexpr int FIRST_ARG_INDEX = 0;
33 constexpr int SECOND_ARG_INDEX = 1;
34 constexpr int THIRD_ARG_INDEX = 2;
35 constexpr int ARGC_NUMBER_ONE = 1;
36 constexpr int ARGC_NUMBER_TWO = 2;
37 constexpr int ARGC_NUMBER_THREE = 3;
38
PreParseParams(napi_env & env,napi_callback_info & info,size_t & argc,napi_value * argv)39 napi_value PreParseParams(napi_env& env, napi_callback_info& info, size_t& argc, napi_value* argv)
40 {
41 napi_value thisVar;
42 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
43 return nullptr;
44 }
45
PerfValueType(const napi_env & env,const napi_value & value,const napi_valuetype expectType)46 bool PerfValueType(const napi_env& env, const napi_value& value, const napi_valuetype expectType)
47 {
48 napi_valuetype valueType;
49 napi_status status = napi_typeof(env, value, &valueType);
50 if (status != napi_ok) {
51 return false;
52 }
53 if (valueType != expectType) {
54 return false;
55 }
56 return true;
57 }
58
GetStringParam(const napi_env & env,const napi_value & value,std::string & dest)59 void GetStringParam(const napi_env& env, const napi_value& value, std::string& dest)
60 {
61 constexpr int nameMaxSize = 1024;
62 char buf[nameMaxSize] = {0};
63 size_t len = 0;
64 napi_get_value_string_utf8(env, value, buf, nameMaxSize, &len);
65 dest = std::string {buf};
66 }
67
ParseStringParam(const napi_env & env,const napi_value & value,std::string & dest)68 bool ParseStringParam(const napi_env& env, const napi_value& value, std::string& dest)
69 {
70 if (PerfValueType(env, value, napi_string)) {
71 GetStringParam(env, value, dest);
72 return true;
73 }
74 if (PerfValueType(env, value, napi_number)) {
75 int64_t destI64;
76 napi_get_value_int64(env, value, &destI64);
77 dest = std::to_string(destI64);
78 return true;
79 }
80 if (PerfValueType(env, value, napi_undefined)) {
81 dest = "undefined";
82 return true;
83 }
84 if (PerfValueType(env, value, napi_null)) {
85 dest = "null";
86 return true;
87 }
88 return false;
89 }
90
ParseInt32Param(const napi_env & env,const napi_value & value,int & dest)91 bool ParseInt32Param(const napi_env& env, const napi_value& value, int& dest)
92 {
93 if (!PerfValueType(env, value, napi_number)) {
94 return false;
95 }
96 napi_get_value_int32(env, value, &dest);
97 return true;
98 }
99
ParseInt64Param(const napi_env & env,const napi_value & value,int64_t & dest)100 bool ParseInt64Param(const napi_env& env, const napi_value& value, int64_t& dest)
101 {
102 if (!PerfValueType(env, value, napi_number)) {
103 return false;
104 }
105 napi_get_value_int64(env, value, &dest);
106 return true;
107 }
108
SceneStart(std::string sceneId,int type,std::string note)109 static void SceneStart(std::string sceneId, int type, std::string note)
110 {
111 PerfMonitor* pMonitor = PerfMonitor::GetPerfMonitor();
112 if (pMonitor != nullptr) {
113 pMonitor->Start(sceneId, static_cast<PerfActionType>(type), note);
114 }
115 }
116
SceneEnd(std::string sceneId,bool isJsApi)117 static void SceneEnd(std::string sceneId, bool isJsApi)
118 {
119 PerfMonitor* pMonitor = PerfMonitor::GetPerfMonitor();
120 if (pMonitor != nullptr) {
121 pMonitor->End(sceneId, isJsApi);
122 }
123 }
124
InputEvent(int type,int sourceType,int64_t time)125 static void InputEvent(int type, int sourceType, int64_t time)
126 {
127 PerfMonitor* pMonitor = PerfMonitor::GetPerfMonitor();
128 if (pMonitor != nullptr) {
129 pMonitor->RecordInputEvent(static_cast<PerfActionType>(type), static_cast<PerfSourceType>(sourceType), time);
130 }
131 }
132
JSSceneStart(napi_env env,napi_callback_info info)133 static napi_value JSSceneStart(napi_env env, napi_callback_info info)
134 {
135 size_t argc = ARGC_NUMBER_THREE;
136 napi_value argv[ARGC_NUMBER_THREE];
137 PreParseParams(env, info, argc, argv);
138 NAPI_ASSERT(env, argc >= ARGC_NUMBER_TWO, "Wrong number of arguments");
139 if (argc < ARGC_NUMBER_TWO) {
140 return nullptr;
141 }
142
143 std::string sceneId = "";
144 if (!ParseStringParam(env, argv[FIRST_ARG_INDEX], sceneId)) {
145 return nullptr;
146 }
147
148 int inputType = 0;
149 if (!ParseInt32Param(env, argv[SECOND_ARG_INDEX], inputType)) {
150 return nullptr;
151 }
152
153 std::string note;
154 if (argc >= ARGC_NUMBER_THREE && !ParseStringParam(env, argv[THIRD_ARG_INDEX], note)) {
155 return nullptr;
156 }
157 SceneStart(sceneId, inputType, note);
158 return nullptr;
159 }
160
JSSceneEnd(napi_env env,napi_callback_info info)161 static napi_value JSSceneEnd(napi_env env, napi_callback_info info)
162 {
163 size_t argc = ARGC_NUMBER_ONE;
164 napi_value argv[ARGC_NUMBER_ONE];
165 PreParseParams(env, info, argc, argv);
166 NAPI_ASSERT(env, argc >= ARGC_NUMBER_ONE, "Wrong number of arguments");
167 if (argc < ARGC_NUMBER_ONE) {
168 return nullptr;
169 }
170
171 std::string sceneId = "";
172 if (!ParseStringParam(env, argv[FIRST_ARG_INDEX], sceneId)) {
173 return nullptr;
174 }
175 SceneEnd(sceneId, true);
176 return nullptr;
177 }
178
JSRecordInputEventTime(napi_env env,napi_callback_info info)179 static napi_value JSRecordInputEventTime(napi_env env, napi_callback_info info)
180 {
181 size_t argc = ARGC_NUMBER_THREE;
182 napi_value argv[ARGC_NUMBER_THREE];
183 PreParseParams(env, info, argc, argv);
184 NAPI_ASSERT(env, argc >= ARGC_NUMBER_TWO, "Wrong number of arguments");
185 if (argc < ARGC_NUMBER_TWO) {
186 return nullptr;
187 }
188
189 int type = 0;
190 if (!ParseInt32Param(env, argv[FIRST_ARG_INDEX], type)) {
191 return nullptr;
192 }
193
194 int sourceType = 0;
195 if (!ParseInt32Param(env, argv[SECOND_ARG_INDEX], sourceType)) {
196 return nullptr;
197 }
198
199 int64_t time = 0;
200 if (!ParseInt64Param(env, argv[THIRD_ARG_INDEX], time)) {
201 return nullptr;
202 }
203 InputEvent(type, sourceType, time);
204 return nullptr;
205 }
206
207
208 /*
209 * function for module exports
210 */
PerfMonitorInit(napi_env env,napi_value exports)211 static napi_value PerfMonitorInit(napi_env env, napi_value exports)
212 {
213 napi_value actionType = nullptr;
214 napi_create_object(env, &actionType);
215 napi_value prop = nullptr;
216 napi_create_uint32(env, LAST_DOWN, &prop);
217 napi_set_named_property(env, actionType, "LAST_DOWN", prop);
218 napi_create_uint32(env, LAST_UP, &prop);
219 napi_set_named_property(env, actionType, "LAST_UP", prop);
220 napi_create_uint32(env, FIRST_MOVE, &prop);
221 napi_set_named_property(env, actionType, "FIRST_MOVE", prop);
222
223 napi_value sourceType = nullptr;
224 napi_create_object(env, &sourceType);
225 prop = nullptr;
226 napi_create_uint32(env, PERF_TOUCH_EVENT, &prop);
227 napi_set_named_property(env, sourceType, "PERF_TOUCH_EVENT", prop);
228 napi_create_uint32(env, PERF_MOUSE_EVENT, &prop);
229 napi_set_named_property(env, sourceType, "PERF_MOUSE_EVENT", prop);
230 napi_create_uint32(env, PERF_TOUCHPAD_EVENT, &prop);
231 napi_set_named_property(env, sourceType, "PERF_TOUCHPAD_EVENT", prop);
232 napi_create_uint32(env, PERF_JOYSTICK_EVENT, &prop);
233 napi_set_named_property(env, sourceType, "PERF_JOYSTICK_EVENT", prop);
234 napi_create_uint32(env, PERF_KEY_EVENT, &prop);
235 napi_set_named_property(env, sourceType, "PERF_KEY_EVENT", prop);
236
237 napi_property_descriptor desc[] = {
238 DECLARE_NAPI_FUNCTION("begin", JSSceneStart),
239 DECLARE_NAPI_FUNCTION("end", JSSceneEnd),
240 DECLARE_NAPI_FUNCTION("recordInputEventTime", JSRecordInputEventTime),
241 DECLARE_NAPI_PROPERTY("ActionType", actionType),
242 DECLARE_NAPI_PROPERTY("SourceType", sourceType),
243 };
244 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
245 return exports;
246 }
247
248 /*
249 * performanceMonitor module definition
250 */
251 static napi_module perfmonitor_module = {
252 .nm_version = 1,
253 .nm_flags = 0,
254 .nm_filename = nullptr,
255 .nm_register_func = PerfMonitorInit,
256 .nm_modname = "arkui.performanceMonitor",
257 .nm_priv = ((void *)0),
258 .reserved = {0}
259 };
260
261 /*
262 * Module registration
263 */
RegisterModule(void)264 extern "C" __attribute__((constructor)) void RegisterModule(void)
265 {
266 napi_module_register(&perfmonitor_module);
267 }
268 }
269