• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <array>
17 #include <iostream>
18 #include <ani.h>
19 #include <hilog/log.h>
20 #include <string>
21 #include "hitrace_meter.h"
22 
23 #ifdef LOG_DOMAIN
24 #undef LOG_DOMAIN
25 #define LOG_DOMAIN 0xD002D33
26 #endif
27 #ifdef LOG_TAG
28 #undef LOG_TAG
29 #define LOG_TAG "HitraceMeterAni"
30 #endif
31 
32 using namespace OHOS::HiviewDFX;
33 static const char NAMESPACE_HITRACEMETER[] = "L@ohos/hiTraceMeter/hiTraceMeter;";
34 constexpr size_t MIN_SIZE = 1;
35 constexpr size_t MAX_SIZE = 1024;
36 
AniStringToStdString(ani_env * env,ani_string aniStr,std::string & content)37 static bool AniStringToStdString(ani_env* env, ani_string aniStr, std::string& content)
38 {
39     ani_size strSize = 0;
40     env->String_GetUTF8Size(aniStr, &strSize);
41 
42     if (strSize < MIN_SIZE || strSize > MAX_SIZE) {
43         return false;
44     }
45     std::vector<char> buffer(strSize + 1);
46     char* charBuffer = buffer.data();
47 
48     ani_size bytesWritten = 0;
49     env->String_GetUTF8(aniStr, charBuffer, strSize + 1, &bytesWritten);
50 
51     charBuffer[bytesWritten] = '\0';
52     content = std::string(charBuffer);
53     return true;
54 }
55 
AniEnumToInt32(ani_env * env,ani_enum_item enumItem,int32_t & value)56 static bool AniEnumToInt32(ani_env* env, ani_enum_item enumItem, int32_t& value)
57 {
58     ani_int aniInt = 0;
59     if (env->EnumItem_GetValue_Int(enumItem, &aniInt) != ANI_OK) {
60         HILOG_ERROR(LOG_CORE, "Failed to get the int32 value of enum.");
61         return false;
62     }
63     value = static_cast<int32_t>(aniInt);
64     return true;
65 }
66 
IsRefUndefined(ani_env * env,ani_ref value)67 static bool IsRefUndefined(ani_env* env, ani_ref value)
68 {
69     ani_boolean isUndefined = ANI_FALSE;
70     env->Reference_IsUndefined(value, &isUndefined);
71     return isUndefined;
72 }
73 
EtsStartTrace(ani_env * env,ani_string name,ani_double taskId)74 static void EtsStartTrace(ani_env* env, ani_string name, ani_double taskId)
75 {
76     std::string nameStr = "";
77     if (!AniStringToStdString(env, name, nameStr)) {
78         HILOG_ERROR(LOG_CORE, "AniStringToStdString failed.");
79         return;
80     }
81     StartAsyncTraceEx(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_APP, nameStr.c_str(), static_cast<int32_t>(taskId), "", "");
82 }
83 
EtsFinishTrace(ani_env * env,ani_string name,ani_double taskId)84 static void EtsFinishTrace(ani_env* env, ani_string name, ani_double taskId)
85 {
86     std::string nameStr = "";
87     if (!AniStringToStdString(env, name, nameStr)) {
88         HILOG_ERROR(LOG_CORE, "AniStringToStdString failed.");
89         return;
90     }
91     FinishAsyncTraceEx(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_APP, nameStr.c_str(), static_cast<int32_t>(taskId));
92 }
93 
EtsCountTrace(ani_env * env,ani_string name,ani_double count)94 static void EtsCountTrace(ani_env* env, ani_string name, ani_double count)
95 {
96     std::string nameStr = "";
97     if (!AniStringToStdString(env, name, nameStr)) {
98         HILOG_ERROR(LOG_CORE, "AniStringToStdString failed.");
99         return;
100     }
101     CountTraceEx(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_APP, nameStr.c_str(), static_cast<int64_t>(count));
102 }
103 
EtsTraceByValue(ani_env * env,ani_enum_item level,ani_string name,ani_double count)104 static void EtsTraceByValue(ani_env* env, ani_enum_item level, ani_string name, ani_double count)
105 {
106     int32_t levelVal = 0;
107     if (!AniEnumToInt32(env, level, levelVal)) {
108         return;
109     }
110     std::string nameStr = "";
111     if (!AniStringToStdString(env, name, nameStr)) {
112         HILOG_ERROR(LOG_CORE, "AniStringToStdString failed.");
113         return;
114     }
115     CountTraceEx(static_cast<HiTraceOutputLevel>(levelVal), HITRACE_TAG_APP, nameStr.c_str(),
116         static_cast<int64_t>(count));
117 }
118 
EtsStartSyncTrace(ani_env * env,ani_enum_item level,ani_string name,ani_object customArgs)119 static void EtsStartSyncTrace(ani_env* env, ani_enum_item level, ani_string name, ani_object customArgs)
120 {
121     int32_t levelVal = 0;
122     if (!AniEnumToInt32(env, level, levelVal)) {
123         return;
124     }
125     std::string nameStr = "";
126     if (!AniStringToStdString(env, name, nameStr)) {
127         HILOG_ERROR(LOG_CORE, "AniStringToStdString failed.");
128         return;
129     }
130     std::string customArgsStr = "";
131     if (!IsRefUndefined(env, static_cast<ani_ref>(customArgs))) {
132         if (!AniStringToStdString(env, static_cast<ani_string>(customArgs), customArgsStr)) {
133             HILOG_ERROR(LOG_CORE, "AniStringToStdString failed.");
134             return;
135         }
136     }
137     StartTraceEx(static_cast<HiTraceOutputLevel>(levelVal), HITRACE_TAG_APP, nameStr.c_str(), customArgsStr.c_str());
138 }
139 
EtsFinishSyncTrace(ani_env * env,ani_enum_item level)140 static void EtsFinishSyncTrace(ani_env* env, ani_enum_item level)
141 {
142     int32_t levelVal = 0;
143     if (!AniEnumToInt32(env, level, levelVal)) {
144         return;
145     }
146     FinishTraceEx(static_cast<HiTraceOutputLevel>(levelVal), HITRACE_TAG_APP);
147 }
148 
EtsStartAsyncTrace(ani_env * env,ani_enum_item level,ani_string name,ani_double taskId,ani_string customCategory,ani_object customArgs)149 static void EtsStartAsyncTrace(ani_env* env, ani_enum_item level, ani_string name, ani_double taskId,
150     ani_string customCategory, ani_object customArgs)
151 {
152     int32_t levelVal = 0;
153     if (!AniEnumToInt32(env, level, levelVal)) {
154         return;
155     }
156     std::string nameStr = "";
157     if (!AniStringToStdString(env, name, nameStr)) {
158         HILOG_ERROR(LOG_CORE, "AniStringToStdString failed.");
159         return;
160     }
161     std::string customCategoryStr = "";
162     if (!AniStringToStdString(env, customCategory, customCategoryStr)) {
163         HILOG_ERROR(LOG_CORE, "AniStringToStdString failed.");
164         return;
165     }
166     std::string customArgsStr = "";
167     if (!IsRefUndefined(env, static_cast<ani_ref>(customArgs))) {
168         if (!AniStringToStdString(env, static_cast<ani_string>(customArgs), customArgsStr)) {
169             HILOG_ERROR(LOG_CORE, "AniStringToStdString failed.");
170             return;
171         }
172     }
173     StartAsyncTraceEx(static_cast<HiTraceOutputLevel>(levelVal), HITRACE_TAG_APP, nameStr.c_str(),
174         static_cast<int32_t>(taskId), customCategoryStr.c_str(), customArgsStr.c_str());
175 }
176 
EtsFinishAsyncTrace(ani_env * env,ani_enum_item level,ani_string name,ani_double taskId)177 static void EtsFinishAsyncTrace(ani_env* env, ani_enum_item level, ani_string name, ani_double taskId)
178 {
179     int32_t levelVal = 0;
180     if (!AniEnumToInt32(env, level, levelVal)) {
181         return;
182     }
183     std::string nameStr = "";
184     if (!AniStringToStdString(env, name, nameStr)) {
185         HILOG_ERROR(LOG_CORE, "AniStringToStdString failed.");
186         return;
187     }
188     FinishAsyncTraceEx(static_cast<HiTraceOutputLevel>(levelVal), HITRACE_TAG_APP, nameStr.c_str(),
189         static_cast<int32_t>(taskId));
190 }
191 
EtsIsTraceEnabled(ani_env * env)192 static ani_boolean EtsIsTraceEnabled(ani_env* env)
193 {
194     return static_cast<ani_boolean>(IsTagEnabled(HITRACE_TAG_APP));
195 }
196 
ANI_Constructor(ani_vm * vm,uint32_t * result)197 ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result)
198 {
199     ani_env* env;
200     if (vm->GetEnv(ANI_VERSION_1, &env) != ANI_OK) {
201         return ANI_ERROR;
202     }
203 
204     ani_namespace ns;
205     if (env->FindNamespace(NAMESPACE_HITRACEMETER, &ns) != ANI_OK) {
206         return ANI_ERROR;
207     }
208 
209     std::array methods = {
210         ani_native_function {"startTrace", nullptr, reinterpret_cast<void *>(EtsStartTrace)},
211         ani_native_function {"finishTrace", nullptr, reinterpret_cast<void *>(EtsFinishTrace)},
212         ani_native_function {"traceByValue", "Lstd/core/String;D:V", reinterpret_cast<void *>(EtsCountTrace)},
213         ani_native_function {"traceByValue", "L@ohos/hiTraceMeter/hiTraceMeter/HiTraceOutputLevel;Lstd/core/String;D:V",
214             reinterpret_cast<void *>(EtsTraceByValue)},
215         ani_native_function {"startSyncTrace", nullptr, reinterpret_cast<void *>(EtsStartSyncTrace)},
216         ani_native_function {"finishSyncTrace", nullptr, reinterpret_cast<void *>(EtsFinishSyncTrace)},
217         ani_native_function {"startAsyncTrace", nullptr, reinterpret_cast<void *>(EtsStartAsyncTrace)},
218         ani_native_function {"finishAsyncTrace", nullptr, reinterpret_cast<void *>(EtsFinishAsyncTrace)},
219         ani_native_function {"isTraceEnabled", nullptr, reinterpret_cast<void *>(EtsIsTraceEnabled)},
220     };
221 
222     if (env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size()) != ANI_OK) {
223         return ANI_ERROR;
224     };
225 
226     *result = ANI_VERSION_1;
227     return ANI_OK;
228 }
229