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 "ets_ability_delegator_utils.h"
17
18 #include <map>
19 #include "ets_ability_delegator.h"
20 #include "hilog_tag_wrapper.h"
21
22 namespace OHOS {
23 namespace AbilityDelegatorEts {
24 namespace {
25 constexpr const char* ABILITY_DELEGATOR_CLASS_NAME = "Lapplication/AbilityDelegator/AbilityDelegatorInner;";
26 constexpr const char* RECORD_CLASS_NAME = "Lescompat/Record;";
27 constexpr const char* VOID_CONTEXT = ":Lapplication/Context/Context;";
28 constexpr const char* STRING_NUMBER_ASYNCCALLBACK = "Lstd/core/String;DLutils/AbilityUtils/AsyncCallbackWrapper;:V";
29 constexpr const char* STRING_VOID = "Lstd/core/String;:V";
30 constexpr const char* MONITOR_ASYNCCALLBACK_VOID =
31 "Lapplication/AbilityMonitor/AbilityMonitor;Lutils/AbilityUtils/AsyncCallbackWrapper;:V";
32 constexpr const char* WANT_ASYNCCALLBACK = "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V";
33 constexpr const char* ARGS_ABILITY_DELEGATOR_CLASS_NAME =
34 "Lapplication/abilityDelegatorArgs/AbilityDelegatorArgsInner;";
35 constexpr const char* SIGNATURE_MONITOR_VOID = "Lapplication/AbilityMonitor/AbilityMonitor;:V";
36 constexpr const char* SIGNATURE_MONITOR_NUMBER_ASYNCCALLBACK =
37 "Lapplication/AbilityMonitor/AbilityMonitor;DLutils/AbilityUtils/AsyncCallbackWrapper;:V";
38 constexpr const char* STAGEMONITOR_ASYNCCALLBACK_VOID =
39 "Lapplication/AbilityStageMonitor/AbilityStageMonitor;Lutils/AbilityUtils/AsyncCallbackWrapper;:V";
40 constexpr const char* STAGEMONITOR_VOID =
41 "Lapplication/AbilityStageMonitor/AbilityStageMonitor;:V";
42 constexpr const char* SIGNATURE_STAGEMONITOR_NUMBER_ASYNCCALLBACK =
43 "Lapplication/AbilityStageMonitor/AbilityStageMonitor;DLutils/AbilityUtils/AsyncCallbackWrapper;:V";
44 constexpr const char* STAGEMONITOR_UIABILITY_ASYNCCALLBACK =
45 "L@ohos/app/ability/UIAbility/UIAbility;Lutils/AbilityUtils/AsyncCallbackWrapper;:V";
46 constexpr const char* STRING_ASYNCCALLBACK_VOID = "Lstd/core/String;Lutils/AbilityUtils/AsyncCallbackWrapper;:V";
47 constexpr const char* STRING_UIABILITY_NUMBER = "L@ohos/app/ability/UIAbility/UIAbility;:D";
48 constexpr const char* STRING_CALLBACK_UIABILITY =
49 "Lutils/AbilityUtils/AsyncCallbackWrapper;:L@ohos/app/ability/UIAbility/UIAbility;";
50 }
51
BindFunctions(ani_env * aniEnv,ani_class abilityDelegator)52 bool BindFunctions(ani_env *aniEnv, ani_class abilityDelegator)
53 {
54 if (aniEnv == nullptr) {
55 return false;
56 }
57 std::array functions = {
58 ani_native_function {"getAppContext", VOID_CONTEXT,
59 reinterpret_cast<void *>(EtsAbilityDelegator::GetAppContext)},
60 ani_native_function {"nativeExecuteShellCommand", STRING_NUMBER_ASYNCCALLBACK,
61 reinterpret_cast<void *>(EtsAbilityDelegator::ExecuteShellCommand)},
62 ani_native_function {"nativeFinishTest", STRING_NUMBER_ASYNCCALLBACK,
63 reinterpret_cast<void *>(EtsAbilityDelegator::FinishTest)},
64 ani_native_function {"printSync", STRING_VOID, reinterpret_cast<void *>(EtsAbilityDelegator::PrintSync)},
65 ani_native_function {"nativeAddAbilityMonitor", MONITOR_ASYNCCALLBACK_VOID,
66 reinterpret_cast<void *>(EtsAbilityDelegator::AddAbilityMonitor)},
67 ani_native_function {"nativeStartAbility", WANT_ASYNCCALLBACK,
68 reinterpret_cast<void *>(EtsAbilityDelegator::StartAbility)},
69 ani_native_function {"addAbilityMonitorSync", SIGNATURE_MONITOR_VOID,
70 reinterpret_cast<void *>(EtsAbilityDelegator::AddAbilityMonitorSync)},
71 ani_native_function {"removeAbilityMonitorAsync", MONITOR_ASYNCCALLBACK_VOID,
72 reinterpret_cast<void *>(EtsAbilityDelegator::RemoveAbilityMonitor)},
73 ani_native_function {"removeAbilityMonitorSync", SIGNATURE_MONITOR_VOID,
74 reinterpret_cast<void *>(EtsAbilityDelegator::RemoveAbilityMonitorSync)},
75 ani_native_function {"waitAbilityMonitorAsync", SIGNATURE_MONITOR_NUMBER_ASYNCCALLBACK,
76 reinterpret_cast<void *>(EtsAbilityDelegator::WaitAbilityMonitor)},
77 ani_native_function {"addAbilityStageMonitorAsync", STAGEMONITOR_ASYNCCALLBACK_VOID,
78 reinterpret_cast<void *>(EtsAbilityDelegator::AddAbilityStageMonitor)},
79 ani_native_function {"addAbilityStageMonitorSync", STAGEMONITOR_VOID,
80 reinterpret_cast<void *>(EtsAbilityDelegator::AddAbilityStageMonitorSync)},
81 ani_native_function {"removeAbilityStageMonitorAsync", STAGEMONITOR_ASYNCCALLBACK_VOID,
82 reinterpret_cast<void *>(EtsAbilityDelegator::RemoveAbilityStageMonitor)},
83 ani_native_function {"removeAbilityStageMonitorSync", STAGEMONITOR_VOID,
84 reinterpret_cast<void *>(EtsAbilityDelegator::RemoveAbilityStageMonitorSync)},
85 ani_native_function {"waitAbilityStageMonitorAsync", SIGNATURE_STAGEMONITOR_NUMBER_ASYNCCALLBACK,
86 reinterpret_cast<void *>(EtsAbilityDelegator::WaitAbilityStageMonitor)},
87 ani_native_function {"doAbilityForegroundAsync", STAGEMONITOR_UIABILITY_ASYNCCALLBACK,
88 reinterpret_cast<void *>(EtsAbilityDelegator::DoAbilityForeground)},
89 ani_native_function {"doAbilityBackgroundAsync", STAGEMONITOR_UIABILITY_ASYNCCALLBACK,
90 reinterpret_cast<void *>(EtsAbilityDelegator::DoAbilityBackground)},
91 ani_native_function {"printAsync", STRING_ASYNCCALLBACK_VOID,
92 reinterpret_cast<void *>(EtsAbilityDelegator::Print)},
93 ani_native_function {"getAbilityState", STRING_UIABILITY_NUMBER,
94 reinterpret_cast<void *>(EtsAbilityDelegator::GetAbilityState)},
95 ani_native_function {"nativeGetCurrentTopAbility", STRING_CALLBACK_UIABILITY,
96 reinterpret_cast<void *>(EtsAbilityDelegator::GetCurrentTopAbility)}
97 };
98 ani_status status = aniEnv->Class_BindNativeMethods(abilityDelegator, functions.data(), functions.size());
99 if (status != ANI_OK) {
100 TAG_LOGE(AAFwkTag::DELEGATOR, "Class_BindNativeMethods failed status: %{public}d", status);
101 return false;
102 }
103 return true;
104 }
105
CreateEtsAbilityDelegator(ani_env * aniEnv)106 ani_object CreateEtsAbilityDelegator(ani_env *aniEnv)
107 {
108 TAG_LOGD(AAFwkTag::DELEGATOR, "CreateEtsAbilityDelegator");
109 if (aniEnv == nullptr) {
110 TAG_LOGE(AAFwkTag::DELEGATOR, "null aniEnv");
111 return {};
112 }
113 ani_class abilityDelegator = nullptr;
114 ani_status status = ANI_ERROR;
115 status = aniEnv->FindClass(ABILITY_DELEGATOR_CLASS_NAME, &abilityDelegator);
116 if (status != ANI_OK) {
117 TAG_LOGE(AAFwkTag::DELEGATOR, "find AbilityDelegatorInner failed status: %{public}d", status);
118 return {};
119 }
120 TAG_LOGD(AAFwkTag::DELEGATOR, "find AbilityDelegator success");
121
122 if (!BindFunctions(aniEnv, abilityDelegator)) {
123 TAG_LOGE(AAFwkTag::DELEGATOR, "BindFunctions failed");
124 return {};
125 }
126
127 ani_method method = nullptr;
128 status = aniEnv->Class_FindMethod(abilityDelegator, "<ctor>", ":V", &method);
129 if (status != ANI_OK) {
130 TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod ctor failed status: %{public}d", status);
131 return {};
132 }
133 TAG_LOGD(AAFwkTag::DELEGATOR, "Class_FindMethod ctor success");
134
135 ani_object object = nullptr;
136 if (aniEnv->Object_New(abilityDelegator, method, &object) != ANI_OK) {
137 TAG_LOGE(AAFwkTag::DELEGATOR, "Object_New failed status: %{public}d", status);
138 return {};
139 }
140
141 TAG_LOGD(AAFwkTag::DELEGATOR, "CreateEtsAbilityDelegator success");
142 return object;
143 }
144
SetBundleName(ani_env * aniEnv,ani_class arguments,ani_object argumentObject,const std::string & bundleName)145 void SetBundleName(ani_env *aniEnv, ani_class arguments, ani_object argumentObject, const std::string &bundleName)
146 {
147 if (aniEnv == nullptr) {
148 TAG_LOGE(AAFwkTag::DELEGATOR, "null aniEnv");
149 return;
150 }
151 ani_status status = ANI_ERROR;
152 ani_string aniStr = nullptr;
153 // Get a ani_string from std::string
154 status = aniEnv->String_NewUTF8(bundleName.c_str(), bundleName.length(), &aniStr);
155 if (status != ANI_OK) {
156 TAG_LOGE(AAFwkTag::DELEGATOR, "String_NewUTF8 failed status: %{public}d", status);
157 return;
158 }
159 TAG_LOGD(AAFwkTag::DELEGATOR, "String_NewUTF8 success");
160
161 // find the setter method
162 ani_method nameSetter = nullptr;
163 status = aniEnv->Class_FindMethod(arguments, "<set>bundleName", nullptr, &nameSetter);
164 if (status != ANI_OK) {
165 TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status);
166 return;
167 }
168 TAG_LOGD(AAFwkTag::DELEGATOR, "Class_FindMethod success");
169
170 // call set bundleName(n:string)
171 status = aniEnv->Object_CallMethod_Void(argumentObject, nameSetter, aniStr);
172 if (status != ANI_OK) {
173 TAG_LOGE(AAFwkTag::DELEGATOR, "Object_CallMethod_Void failed status: %{public}d", status);
174 return;
175 }
176 TAG_LOGD(AAFwkTag::DELEGATOR, "Object_CallMethod_Void success");
177 }
178
SetParameters(ani_env * aniEnv,ani_class arguments,ani_object argumentObject,const std::map<std::string,std::string> & paras)179 void SetParameters(ani_env *aniEnv, ani_class arguments, ani_object argumentObject,
180 const std::map<std::string, std::string> ¶s)
181 {
182 TAG_LOGD(AAFwkTag::DELEGATOR, "SetParameters begin");
183 if (aniEnv == nullptr) {
184 TAG_LOGE(AAFwkTag::DELEGATOR, "null aniEnv");
185 return;
186 }
187 ani_status status = ANI_ERROR;
188 ani_class recordCls = nullptr;
189 status = aniEnv->FindClass(RECORD_CLASS_NAME, &recordCls);
190 if (status != ANI_OK) {
191 TAG_LOGE(AAFwkTag::DELEGATOR, "FindClass failed status: %{public}d", status);
192 return;
193 }
194 ani_method recordGetMethod = nullptr;
195 status = aniEnv->Class_FindMethod(recordCls, "$_get", "Lstd/core/Object;:Lstd/core/Object;", &recordGetMethod);
196 if (status != ANI_OK) {
197 TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status);
198 return;
199 }
200 ani_method recordSetMethod = nullptr;
201 status = aniEnv->Class_FindMethod(recordCls, "$_set", "Lstd/core/Object;Lstd/core/Object;:V", &recordSetMethod);
202 if (status != ANI_OK) {
203 TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status);
204 return;
205 }
206 ani_ref parameterRef = nullptr;
207 status = aniEnv->Object_CallMethodByName_Ref(argumentObject, "<get>parameters", ":Lescompat/Record;",
208 ¶meterRef);
209 if (status != ANI_OK) {
210 TAG_LOGE(AAFwkTag::DELEGATOR, "Object_CallMethodByName_Ref failed status: %{public}d", status);
211 return;
212 }
213 ani_object parameterObject = static_cast<ani_object>(parameterRef);
214 for (auto iter = paras.begin(); iter != paras.end(); ++iter) {
215 std::string key = iter->first;
216 std::string value = iter->second;
217 ani_string ani_key = nullptr;
218 ani_string ani_value = nullptr;
219 status = aniEnv->String_NewUTF8(key.c_str(), key.length(), &ani_key);
220 if (status != ANI_OK) {
221 TAG_LOGE(AAFwkTag::DELEGATOR, "String_NewUTF8 key failed status: %{public}d", status);
222 return;
223 }
224 status = aniEnv->String_NewUTF8(value.c_str(), value.length(), &ani_value);
225 if (status != ANI_OK) {
226 TAG_LOGE(AAFwkTag::DELEGATOR, "String_NewUTF8 value failed status: %{public}d", status);
227 return;
228 }
229 status = aniEnv->Object_CallMethod_Void(parameterObject, recordSetMethod, ani_key, ani_value);
230 if (status != ANI_OK) {
231 TAG_LOGE(AAFwkTag::DELEGATOR, "Object_CallMethod_Void failed status: %{public}d", status);
232 return;
233 }
234 }
235 TAG_LOGD(AAFwkTag::DELEGATOR, "SetParameters end");
236 }
237
SetTestCaseNames(ani_env * aniEnv,ani_class arguments,ani_object argumentObject,const std::string & testcaseNames)238 void SetTestCaseNames(ani_env *aniEnv, ani_class arguments, ani_object argumentObject, const std::string &testcaseNames)
239 {
240 if (aniEnv == nullptr) {
241 TAG_LOGE(AAFwkTag::DELEGATOR, "null aniEnv");
242 return;
243 }
244 ani_status status = ANI_ERROR;
245 ani_string aniStr = nullptr;
246 status = aniEnv->String_NewUTF8(testcaseNames.c_str(), testcaseNames.length(), &aniStr);
247 if (status != ANI_OK) {
248 TAG_LOGE(AAFwkTag::DELEGATOR, "String_NewUTF8 failed status: %{public}d", status);
249 return;
250 }
251 TAG_LOGD(AAFwkTag::DELEGATOR, "String_NewUTF8 success");
252
253 // find the setter method
254 ani_method nameSetter = nullptr;
255 status = aniEnv->Class_FindMethod(arguments, "<set>testCaseNames", nullptr, &nameSetter);
256 if (status != ANI_OK) {
257 TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status);
258 return;
259 }
260 TAG_LOGD(AAFwkTag::DELEGATOR, "Class_FindMethod success");
261
262 // call set testcaseNames(n:string)
263 status = aniEnv->Object_CallMethod_Void(argumentObject, nameSetter, aniStr);
264 if (status != ANI_OK) {
265 TAG_LOGE(AAFwkTag::DELEGATOR, "Object_CallMethod_Void failed status: %{public}d", status);
266 return;
267 }
268 TAG_LOGD(AAFwkTag::DELEGATOR, "Object_CallMethod_Void success");
269 }
270
SetTestRunnerClassName(ani_env * aniEnv,ani_class arguments,ani_object argumentObject,const std::string & className)271 void SetTestRunnerClassName(ani_env *aniEnv, ani_class arguments, ani_object argumentObject,
272 const std::string &className)
273 {
274 if (aniEnv == nullptr) {
275 TAG_LOGE(AAFwkTag::DELEGATOR, "null aniEnv");
276 return;
277 }
278 ani_status status = ANI_ERROR;
279 ani_string aniStr = nullptr;
280 status = aniEnv->String_NewUTF8(className.c_str(), className.length(), &aniStr);
281 if (status != ANI_OK) {
282 TAG_LOGE(AAFwkTag::DELEGATOR, "String_NewUTF8 failed status: %{public}d", status);
283 return;
284 }
285 TAG_LOGD(AAFwkTag::DELEGATOR, "String_NewUTF8 success");
286
287 // find the setter method
288 ani_method nameSetter = nullptr;
289 status = aniEnv->Class_FindMethod(arguments, "<set>testRunnerClassName", nullptr, &nameSetter);
290 if (status != ANI_OK) {
291 TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status);
292 return;
293 }
294 TAG_LOGD(AAFwkTag::DELEGATOR, "Class_FindMethod success");
295
296 // call set testRunnerClassName(n:string)
297 status = aniEnv->Object_CallMethod_Void(argumentObject, nameSetter, aniStr);
298 if (status != ANI_OK) {
299 TAG_LOGE(AAFwkTag::DELEGATOR, "Object_CallMethod_Void failed status: %{public}d", status);
300 return;
301 }
302 TAG_LOGD(AAFwkTag::DELEGATOR, "Object_CallMethod_Void success");
303 }
304
CreateEtsAbilityDelegatorArguments(ani_env * aniEnv,const std::shared_ptr<AppExecFwk::AbilityDelegatorArgs> abilityDelegatorArgs)305 ani_object CreateEtsAbilityDelegatorArguments(
306 ani_env *aniEnv, const std::shared_ptr<AppExecFwk::AbilityDelegatorArgs> abilityDelegatorArgs)
307 {
308 TAG_LOGD(AAFwkTag::DELEGATOR, "CreateJsAbilityDelegatorArguments");
309 if (aniEnv == nullptr || abilityDelegatorArgs == nullptr) {
310 TAG_LOGE(AAFwkTag::DELEGATOR, "null aniEnv or abilityDelegatorArgs");
311 return {};
312 }
313 ani_class arguments = nullptr;
314 ani_status status = ANI_ERROR;
315 status = aniEnv->FindClass(ARGS_ABILITY_DELEGATOR_CLASS_NAME, &arguments);
316 if (status != ANI_OK) {
317 TAG_LOGE(AAFwkTag::DELEGATOR, "find abilityDelegatorArgs failed status: %{public}d", status);
318 return {};
319 }
320 TAG_LOGD(AAFwkTag::DELEGATOR, "find AbilityDelegatorArgs success");
321
322 ani_method method = nullptr;
323 status = aniEnv->Class_FindMethod(arguments, "<ctor>", ":V", &method);
324 if (status != ANI_OK) {
325 TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod ctor failed status: %{public}d", status);
326 return {};
327 }
328 TAG_LOGD(AAFwkTag::DELEGATOR, "Class_FindMethod ctor success");
329
330 ani_object argumentObject = nullptr;
331 status = aniEnv->Object_New(arguments, method, &argumentObject);
332 if (status != ANI_OK) {
333 TAG_LOGE(AAFwkTag::DELEGATOR, "Object_New failed status: %{public}d", status);
334 return {};
335 }
336 TAG_LOGD(AAFwkTag::DELEGATOR, "Object_New success");
337
338 std::string bundleName = abilityDelegatorArgs->GetTestBundleName();
339 SetBundleName(aniEnv, arguments, argumentObject, bundleName);
340
341 std::string testcaseName = abilityDelegatorArgs->GetTestCaseName();
342 SetTestCaseNames(aniEnv, arguments, argumentObject, testcaseName);
343
344 std::string className = abilityDelegatorArgs->GetTestRunnerClassName();
345 SetTestRunnerClassName(aniEnv, arguments, argumentObject, className);
346
347 auto parameters = abilityDelegatorArgs->GetTestParam();
348 SetParameters(aniEnv, arguments, argumentObject, parameters);
349
350 return argumentObject;
351 }
352 } // namespace AbilityDelegatorEts
353 } // namespace OHOS
354