1 /*
2 * Copyright (c) 2025 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 "sts_events_json_common.h"
17 #include <cstring>
18 #include "event_logger.h"
19 #include "securec.h"
20
21 namespace OHOS {
22 namespace AppExecFwk {
23 namespace {
24 DEFINE_EH_HILOG_LABEL("EventsEmitter");
25 }
26 constexpr const char* CLASSNAME_DOUBLE = "Lstd/core/Double;";
27 constexpr const char* CLASSNAME_BOOLEAN = "Lstd/core/Boolean;";
28
GetIntByName(ani_env * env,ani_object param,const char * name,int32_t & value)29 bool GetIntByName(ani_env *env, ani_object param, const char *name, int32_t &value)
30 {
31 ani_int res = 0;
32 auto status = env->Object_GetFieldByName_Int(param, name, &res);
33 if (status != ANI_OK) {
34 HILOGI("status : %{public}d", status);
35 return false;
36 }
37
38 value = static_cast<int32_t>(res);
39 return true;
40 }
41
GetDoubleOrUndefined(ani_env * env,ani_object param,const char * name,ani_double & value)42 bool GetDoubleOrUndefined(ani_env *env, ani_object param, const char *name, ani_double &value)
43 {
44 ani_ref obj = nullptr;
45 ani_boolean isUndefined = true;
46 ani_status status = ANI_ERROR;
47
48 if ((status = env->Object_GetFieldByName_Ref(param, name, &obj)) != ANI_OK) {
49 HILOGI("status : %{public}d", status);
50 return false;
51 }
52 if ((status = env->Reference_IsUndefined(obj, &isUndefined)) != ANI_OK) {
53 HILOGI("status : %{public}d", status);
54 return false;
55 }
56 if (isUndefined) {
57 HILOGI("%{public}s : undefined", name);
58 return false;
59 }
60 if ((status = env->Object_CallMethodByName_Double(
61 reinterpret_cast<ani_object>(obj), "unboxed", nullptr, &value)) != ANI_OK) {
62 HILOGI("status : %{public}d", status);
63 return false;
64 }
65 return true;
66 }
67
GetBoolOrUndefined(ani_env * env,ani_object param,const char * name)68 bool GetBoolOrUndefined(ani_env *env, ani_object param, const char *name)
69 {
70 ani_ref obj = nullptr;
71 ani_boolean isUndefined = true;
72 ani_status status = ANI_ERROR;
73 ani_boolean res = 0.0;
74
75 if ((status = env->Object_GetFieldByName_Ref(param, name, &obj)) != ANI_OK) {
76 HILOGI("status : %{public}d", status);
77 return res;
78 }
79 if ((status = env->Reference_IsUndefined(obj, &isUndefined)) != ANI_OK) {
80 HILOGI("status : %{public}d", status);
81 return res;
82 }
83 if (isUndefined) {
84 HILOGI("%{public}s : undefined", name);
85 return res;
86 }
87 if ((status = env->Object_CallMethodByName_Boolean(
88 reinterpret_cast<ani_object>(obj), "booleanValue", nullptr, &res)) != ANI_OK) {
89 HILOGI("status : %{public}d", status);
90 return res;
91 }
92 return res;
93 }
94
GetStringOrUndefined(ani_env * env,ani_object param,const char * name,std::string & res)95 bool GetStringOrUndefined(ani_env *env, ani_object param, const char *name, std::string &res)
96 {
97 ani_ref obj = nullptr;
98 ani_boolean isUndefined = true;
99 ani_status status = ANI_ERROR;
100
101 if ((status = env->Object_GetFieldByName_Ref(param, name, &obj)) != ANI_OK) {
102 HILOGI("status : %{public}d", status);
103 return false;
104 }
105 if ((status = env->Reference_IsUndefined(obj, &isUndefined)) != ANI_OK) {
106 HILOGI("status : %{public}d", status);
107 return false;
108 }
109 if (isUndefined) {
110 HILOGI("%{public}s : undefined", name);
111 return false;
112 }
113 if (!GetStdString(env, reinterpret_cast<ani_string>(obj), res)) {
114 HILOGI("GetStdString failed");
115 return false;
116 }
117 return true;
118 }
119
GetFixedStringArrayOrUndefined(ani_env * env,ani_object param,const char * name,std::vector<std::string> & res)120 bool GetFixedStringArrayOrUndefined(ani_env *env, ani_object param, const char *name, std::vector<std::string> &res)
121 {
122 ani_ref obj = nullptr;
123 ani_status status;
124
125 if ((status = env->Object_GetFieldByName_Ref(param, name, &obj)) != ANI_OK) {
126 HILOGI("status : %{public}d", status);
127 return false;
128 }
129 ani_boolean isUndefined = true;
130 if ((status = env->Reference_IsUndefined(obj, &isUndefined)) != ANI_OK) {
131 HILOGI("status : %{public}d", status);
132 return false;
133 }
134 if (isUndefined) {
135 HILOGI("%{public}s : undefined", name);
136 return false;
137 }
138
139 ani_size size = 0;
140 if ((status = env->Array_GetLength(reinterpret_cast<ani_array>(obj), &size)) != ANI_OK) {
141 HILOGI("status : %{public}d", status);
142 return false;
143 }
144
145 ani_ref ref = nullptr;
146 for (ani_size index = 0; index < size; index++) {
147 if ((status = env->Array_Get_Ref(reinterpret_cast<ani_array_ref>(obj), index, &ref)) != ANI_OK) {
148 HILOGI("status : %{public}d, index: %{public}zu", status, index);
149 return false;
150 }
151
152 std::string strItem = "";
153 if (!GetStdString(env, reinterpret_cast<ani_string>(ref), strItem)) {
154 HILOGI("GetStdString failed, index: %{public}zu", index);
155 return false;
156 }
157
158 res.push_back(strItem);
159 }
160
161 return true;
162 }
163
SetFieldFixedArrayString(ani_env * env,ani_class cls,ani_object object,const std::string & fieldName,const std::vector<std::string> & values)164 bool SetFieldFixedArrayString(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName,
165 const std::vector<std::string> &values)
166 {
167 ani_field field = nullptr;
168 ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field);
169 if (status != ANI_OK) {
170 HILOGI("status : %{public}d", status);
171 return false;
172 }
173
174 ani_class stringCls = nullptr;
175 status = env->FindClass("Lstd/core/String;", &stringCls);
176 if (status != ANI_OK) {
177 HILOGI("status : %{public}d", status);
178 return false;
179 }
180
181 ani_ref undefinedRef = nullptr;
182 status = env->GetUndefined(&undefinedRef);
183 if (status != ANI_OK) {
184 HILOGI("status : %{public}d", status);
185 return false;
186 }
187
188 ani_array_ref array = nullptr;
189 status = env->Array_New_Ref(stringCls, values.size(), undefinedRef, &array);
190 if (status != ANI_OK) {
191 HILOGI("status : %{public}d", status);
192 return false;
193 }
194
195 for (size_t i = 0; i < values.size(); ++i) {
196 ani_string strItem = nullptr;
197 status = env->String_NewUTF8(values[i].c_str(), values[i].size(), &strItem);
198 if (status != ANI_OK) {
199 HILOGI("status : %{public}d", status);
200 return false;
201 }
202 status = env->Array_Set_Ref(array, i, strItem);
203 if (status != ANI_OK) {
204 HILOGI("status : %{public}d", status);
205 return false;
206 }
207 }
208 status = env->Object_SetField_Ref(object, field, array);
209 if (status != ANI_OK) {
210 HILOGI("status : %{public}d", status);
211 return false;
212 }
213 return true;
214 }
215
GetStringArrayOrUndefined(ani_env * env,ani_object param,const char * name,std::vector<std::string> & res)216 bool GetStringArrayOrUndefined(ani_env *env, ani_object param, const char *name, std::vector<std::string> &res)
217 {
218 ani_ref arrayObj = nullptr;
219 ani_boolean isUndefined = true;
220 ani_status status = ANI_OK;
221 ani_double length;
222
223 if ((status = env->Object_GetFieldByName_Ref(param, name, &arrayObj)) != ANI_OK) {
224 HILOGI("status : %{public}d", status);
225 return false;
226 }
227 if ((status = env->Reference_IsUndefined(arrayObj, &isUndefined)) != ANI_OK) {
228 HILOGI("status : %{public}d", status);
229 return false;
230 }
231 if (isUndefined) {
232 HILOGI("%{public}s : undefined", name);
233 return false;
234 }
235
236 status = env->Object_GetPropertyByName_Double(reinterpret_cast<ani_object>(arrayObj), "length", &length);
237 if (status != ANI_OK) {
238 HILOGI("status : %{public}d", status);
239 return false;
240 }
241
242 for (int32_t index = 0; index < static_cast<int32_t>(length); index++) {
243 ani_ref stringEntryRef;
244 status = env->Object_CallMethodByName_Ref(reinterpret_cast<ani_object>(arrayObj),
245 "$_get", "I:Lstd/core/Object;", &stringEntryRef, static_cast<ani_int>(index));
246 if (status != ANI_OK) {
247 HILOGI("status : %{public}d, index: %{public}d", status, index);
248 return false;
249 }
250
251 std::string str = "";
252 if (!GetStdString(env, reinterpret_cast<ani_string>(stringEntryRef), str)) {
253 HILOGI("GetStdString failed, index: %{public}d", index);
254 return false;
255 }
256
257 res.push_back(str);
258 }
259
260 return true;
261 }
262
263
SetFieldArrayString(ani_env * env,ani_class cls,ani_object object,const std::string & fieldName,const std::vector<std::string> & values)264 bool SetFieldArrayString(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName,
265 const std::vector<std::string> &values)
266 {
267 ani_field field = nullptr;
268 ani_class arrayCls = nullptr;
269 ani_method arrayCtor;
270 ani_object arrayObj;
271
272 ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field);
273 if (status != ANI_OK) {
274 HILOGI("status : %{public}d", status);
275 return false;
276 }
277
278 status = env->FindClass("Lescompat/Array;", &arrayCls);
279 if (status != ANI_OK) {
280 HILOGI("status : %{public}d", status);
281 return false;
282 }
283
284 status = env->Class_FindMethod(arrayCls, "<ctor>", "I:V", &arrayCtor);
285 if (status != ANI_OK) {
286 HILOGI("status : %{public}d", status);
287 return false;
288 }
289
290 status = env->Object_New(arrayCls, arrayCtor, &arrayObj, values.size());
291 if (status != ANI_OK) {
292 HILOGI("status : %{public}d", status);
293 return false;
294 }
295
296 for (size_t i = 0; i < values.size(); i++) {
297 ani_string strItem = nullptr;
298 status = env->String_NewUTF8(values[i].c_str(), values[i].size(), &strItem);
299 if (status != ANI_OK) {
300 HILOGI("status : %{public}d", status);
301 return false;
302 }
303
304 status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", i, strItem);
305 if (status != ANI_OK) {
306 HILOGI("status : %{public}d", status);
307 return false;
308 }
309 }
310 status = env->Object_SetField_Ref(object, field, arrayObj);
311 if (status != ANI_OK) {
312 HILOGI("status : %{public}d", status);
313 return false;
314 }
315
316 return true;
317 }
318
GetStdString(ani_env * env,ani_string str,std::string & res)319 bool GetStdString(ani_env *env, ani_string str, std::string &res)
320 {
321 ani_size sz {};
322 ani_status status = ANI_ERROR;
323 if ((status = env->String_GetUTF8Size(str, &sz)) != ANI_OK) {
324 HILOGW("status : %{public}d", status);
325 return false;
326 }
327 res.resize(sz + 1);
328 if ((status = env->String_GetUTF8SubString(str, 0, sz, res.data(), res.size(), &sz)) != ANI_OK) {
329 HILOGI("status : %{public}d", status);
330 return false;
331 }
332 res.resize(sz);
333 return true;
334 }
335
GetAniString(ani_env * env,const std::string & str)336 ani_string GetAniString(ani_env *env, const std::string &str)
337 {
338 ani_string aniStr = nullptr;
339 ani_status status = env->String_NewUTF8(str.c_str(), str.size(), &aniStr);
340 if (status != ANI_OK) {
341 HILOGI("status : %{public}d", status);
342 return nullptr;
343 }
344 return aniStr;
345 }
346
GetAniArrayString(ani_env * env,const std::vector<std::string> & values)347 ani_array_ref GetAniArrayString(ani_env *env, const std::vector<std::string> &values)
348 {
349 ani_array_ref aArrayRef = nullptr;
350 return aArrayRef;
351 }
352
GetRefPropertyByName(ani_env * env,ani_object param,const char * name,ani_ref & ref)353 bool GetRefPropertyByName(ani_env *env, ani_object param, const char *name, ani_ref &ref)
354 {
355 ani_status status = ANI_ERROR;
356 if ((status = env->Object_GetPropertyByName_Ref(param, name, &ref)) != ANI_OK) {
357 HILOGI("Object_GetFieldByName_Ref failed, status : %{public}d", status);
358 return false;
359 }
360
361 ani_boolean isUndefined = true;
362 if ((status = env->Reference_IsUndefined(ref, &isUndefined)) != ANI_OK) {
363 HILOGI("Reference_IsUndefined failed, status : %{public}d", status);
364 return false;
365 }
366 if (isUndefined) {
367 HILOGI("wantParams is undefined");
368 return false;
369 }
370 isUndefined = true;
371
372 if ((status = env->Reference_IsNull(ref, &isUndefined)) != ANI_OK) {
373 HILOGI("Reference_IsNull failed, status : %{public}d", status);
374 return false;
375 }
376
377 if (isUndefined) {
378 HILOGI("wantParams is null");
379 return false;
380 }
381 isUndefined = true;
382
383 if ((status = env->Reference_IsNullishValue(ref, &isUndefined)) != ANI_OK) {
384 HILOGI("Reference_IsNullishValue failed, status : %{public}d", status);
385 return false;
386 }
387
388 if (isUndefined) {
389 HILOGI("wantParams is nullish");
390 return false;
391 }
392 return true;
393 }
394
createDouble(ani_env * env,ani_double value)395 ani_object createDouble(ani_env *env, ani_double value)
396 {
397 ani_class persion_cls;
398 ani_status status = ANI_ERROR;
399 if ((status = env->FindClass(CLASSNAME_DOUBLE, &persion_cls)) != ANI_OK) {
400 HILOGI("status : %{public}d", status);
401 return nullptr;
402 }
403 ani_method personInfoCtor;
404 if ((status = env->Class_FindMethod(persion_cls, "<ctor>", "D:V", &personInfoCtor)) != ANI_OK) {
405 HILOGI("status : %{public}d", status);
406 return nullptr;
407 }
408 ani_object personInfoObj;
409 if ((status = env->Object_New(persion_cls, personInfoCtor, &personInfoObj, value)) != ANI_OK) {
410 HILOGI("status : %{public}d", status);
411 return nullptr;
412 }
413 return personInfoObj;
414 }
415
createBoolean(ani_env * env,ani_boolean value)416 ani_object createBoolean(ani_env *env, ani_boolean value)
417 {
418 ani_class persion_cls;
419 ani_status status = ANI_ERROR;
420 if ((status = env->FindClass(CLASSNAME_BOOLEAN, &persion_cls)) != ANI_OK) {
421 HILOGI("status : %{public}d", status);
422 return nullptr;
423 }
424 ani_method personInfoCtor;
425 if ((status = env->Class_FindMethod(persion_cls, "<ctor>", "Z:V", &personInfoCtor)) != ANI_OK) {
426 HILOGI("status : %{public}d", status);
427 return nullptr;
428 }
429 ani_object personInfoObj;
430 if ((status = env->Object_New(persion_cls, personInfoCtor, &personInfoObj, value)) != ANI_OK) {
431 HILOGI("status : %{public}d", status);
432 return nullptr;
433 }
434 return personInfoObj;
435 }
436
SetFieldString(ani_env * env,ani_class cls,ani_object object,const std::string & fieldName,const std::string & value)437 bool SetFieldString(ani_env *env, ani_class cls, ani_object object,
438 const std::string &fieldName, const std::string &value)
439 {
440 ani_field field = nullptr;
441 ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field);
442 if (status != ANI_OK) {
443 HILOGI("status : %{public}d", status);
444 return false;
445 }
446
447 if (value.empty()) {
448 ani_ref nullRef = nullptr;
449 if ((status = env->GetNull(&nullRef)) != ANI_OK) {
450 HILOGI("status : %{public}d", status);
451 return false;
452 }
453 if ((status = env->Object_SetField_Ref(object, field, nullRef)) != ANI_OK) {
454 HILOGI("status : %{public}d", status);
455 return false;
456 }
457 return true;
458 }
459
460 ani_string strItem = nullptr;
461 if ((status = env->String_NewUTF8(value.c_str(), value.size(), &strItem)) != ANI_OK) {
462 HILOGI("status : %{public}d", status);
463 return false;
464 }
465
466 if ((status = env->Object_SetField_Ref(object, field, strItem)) != ANI_OK) {
467 HILOGI("status : %{public}d", status);
468 return false;
469 }
470 return true;
471 }
472
SetFieldDouble(ani_env * env,ani_class cls,ani_object object,const std::string & fieldName,double value)473 bool SetFieldDouble(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, double value)
474 {
475 ani_field field = nullptr;
476 ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field);
477 if (status != ANI_OK) {
478 HILOGI("status : %{public}d", status);
479 return false;
480 }
481
482 status = env->Object_SetField_Double(object, field, value);
483 if (status != ANI_OK) {
484 HILOGI("status : %{public}d", status);
485 return false;
486 }
487 return true;
488 }
489
SetFieldBoolean(ani_env * env,ani_class cls,ani_object object,const std::string & fieldName,bool value)490 bool SetFieldBoolean(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, bool value)
491 {
492 ani_field field = nullptr;
493 ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field);
494 if (status != ANI_OK) {
495 HILOGI("status : %{public}d", status);
496 return false;
497 }
498 status = env->Object_SetField_Boolean(object, field, value);
499 if (status != ANI_OK) {
500 HILOGI("status : %{public}d", status);
501 return false;
502 }
503 return true;
504 }
505
SetFieldInt(ani_env * env,ani_class cls,ani_object object,const std::string & fieldName,int32_t value)506 bool SetFieldInt(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, int32_t value)
507 {
508 ani_field field = nullptr;
509 ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field);
510 if (status != ANI_OK) {
511 HILOGI("status : %{public}d, field name: %{public}s", status, fieldName.c_str());
512 return false;
513 }
514 status = env->Object_SetField_Int(object, field, value);
515 if (status != ANI_OK) {
516 HILOGI("status : %{public}d, field name: %{public}s", status, fieldName.c_str());
517 return false;
518 }
519 return true;
520 }
521
SetFieldRef(ani_env * env,ani_class cls,ani_object object,const std::string & fieldName,ani_ref value)522 bool SetFieldRef(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, ani_ref value)
523 {
524 ani_field field = nullptr;
525 ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field);
526 if (status != ANI_OK) {
527 HILOGI("FindField %{public}s failed, status: %{public}d", fieldName.c_str(), status);
528 return false;
529 }
530 status = env->Object_SetField_Ref(object, field, value);
531 if (status != ANI_OK) {
532 HILOGI("SetField_Ref %{public}s failed, status: %{public}d", fieldName.c_str(), status);
533 return false;
534 }
535 return true;
536 }
537 } // namespace AppExecFwk
538 } // namespace OHOS