1 /*
2 * Copyright (c) 2022-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 "simulator.h"
17
18 #include <condition_variable>
19 #include <fstream>
20 #include <functional>
21 #include <mutex>
22 #include <thread>
23 #include <unordered_map>
24
25 #include "EventHandler.h"
26 #include "StageContext.h"
27 #include "ability_context.h"
28 #include "ability_stage_context.h"
29 #include "hilog_wrapper.h"
30 #include "js_ability_context.h"
31 #include "js_ability_stage_context.h"
32 #include "js_console_log.h"
33 #include "js_data_converter.h"
34 #include "js_module_searcher.h"
35 #include "js_runtime.h"
36 #include "js_runtime_utils.h"
37 #include "js_timer.h"
38 #include "js_window_stage.h"
39 #include "launch_param.h"
40 #include "native_engine/impl/ark/ark_native_engine.h"
41 #include "resource_manager.h"
42 #include "window_scene.h"
43
44 extern const char _binary_jsMockSystemPlugin_abc_start[];
45 extern const char _binary_jsMockSystemPlugin_abc_end[];
46
47 namespace OHOS {
48 namespace AbilityRuntime {
49 namespace {
50 constexpr int64_t DEFAULT_GC_POOL_SIZE = 0x10000000; // 256MB
51 constexpr int32_t DEFAULT_ARK_PROPERTIES = -1;
52 constexpr size_t DEFAULT_GC_THREAD_NUM = 7;
53 constexpr size_t DEFAULT_LONG_PAUSE_TIME = 40;
54
55 constexpr char BUNDLE_INSTALL_PATH[] = "/data/storage/el1/bundle/";
56
57 #if defined(WINDOWS_PLATFORM)
58 constexpr char ARK_DEBUGGER_LIB_PATH[] = "libark_debugger.dll";
59 #elif defined(MAC_PLATFORM)
60 constexpr char ARK_DEBUGGER_LIB_PATH[] = "libark_debugger.dylib";
61 #else
62 #error "Unsupported platform"
63 #endif
64
PrintVmLog(int32_t,int32_t,const char *,const char *,const char * message)65 int32_t PrintVmLog(int32_t, int32_t, const char*, const char*, const char *message)
66 {
67 HILOG_DEBUG("ArkLog: %{public}s", message);
68 return 0;
69 }
70
71 template<typename T, size_t N>
ArraySize(T (&)[N])72 inline constexpr size_t ArraySize(T (&)[N]) noexcept
73 {
74 return N;
75 }
76
77 struct DebuggerTask {
78 void OnPostTask(std::function<void()> &&task);
79
80 static void HandleTask(const uv_async_t *req);
81
82 uv_async_t onPostTaskSignal {};
83 std::function<void()> func;
84 };
85
86 class SimulatorImpl : public Simulator {
87 public:
88 SimulatorImpl() = default;
89 ~SimulatorImpl();
90
91 bool Initialize(const Options &options);
92
93 int64_t StartAbility(const std::string &abilityName, TerminateCallback callback) override;
94 void TerminateAbility(int64_t abilityId) override;
95 void UpdateConfiguration(const AppExecFwk::Configuration &config) override;
96 private:
97 bool OnInit();
98 void Run();
99 NativeValue *LoadScript(const std::string &srcPath);
100 void InitResourceMgr();
101 void InitJsAbilityContext(NativeValue *instanceValue);
102 void DispatchStartLifecycle(NativeValue *instanceValue);
103 std::unique_ptr<NativeReference> CreateJsWindowStage(const std::shared_ptr<Rosen::WindowScene> &windowScene);
104 NativeValue *CreateJsWant(NativeEngine &engine);
105 bool LoadAbilityStage(uint8_t *buffer, size_t len);
106 void InitJsAbilityStageContext(NativeValue *instanceValue);
107 NativeValue *CreateJsLaunchParam(NativeEngine &engine);
108
109 panda::ecmascript::EcmaVM *CreateJSVM();
110 Options options_;
111 std::string abilityPath_;
112 panda::ecmascript::EcmaVM *vm_ = nullptr;
113 DebuggerTask debuggerTask_;
114 std::unique_ptr<NativeEngine> nativeEngine_;
115
116 int64_t currentId_ = 0;
117 std::unordered_map<int64_t, std::shared_ptr<NativeReference>> abilities_;
118 std::unordered_map<int64_t, std::shared_ptr<Rosen::WindowScene>> windowScenes_;
119 std::unordered_map<int64_t, std::shared_ptr<NativeReference>> jsWindowStages_;
120 std::unordered_map<int64_t, std::shared_ptr<NativeReference>> jsContexts_;
121 std::shared_ptr<Global::Resource::ResourceManager> resourceMgr_;
122 std::shared_ptr<AbilityContext> context_;
123 std::shared_ptr<NativeReference> abilityStage_;
124 std::shared_ptr<AbilityStageContext> stageContext_;
125 std::shared_ptr<NativeReference> jsStageContext_;
126 };
127
HandleTask(const uv_async_t * req)128 void DebuggerTask::HandleTask(const uv_async_t *req)
129 {
130 auto *debuggerTask = reinterpret_cast<DebuggerTask*>(req->data);
131 if (debuggerTask == nullptr) {
132 HILOG_ERROR("HandleTask debuggerTask is null");
133 return;
134 }
135 debuggerTask->func();
136 }
137
OnPostTask(std::function<void ()> && task)138 void DebuggerTask::OnPostTask(std::function<void()> &&task)
139 {
140 if (uv_is_active((uv_handle_t*)&onPostTaskSignal)) {
141 func = std::move(task);
142 onPostTaskSignal.data = static_cast<void*>(this);
143 uv_async_send(&onPostTaskSignal);
144 }
145 }
146
~SimulatorImpl()147 SimulatorImpl::~SimulatorImpl()
148 {
149 if (nativeEngine_) {
150 uv_close(reinterpret_cast<uv_handle_t*>(&debuggerTask_.onPostTaskSignal), nullptr);
151 uv_loop_t *uvLoop = nativeEngine_->GetUVLoop();
152 if (uvLoop != nullptr) {
153 uv_work_t work;
154 uv_queue_work(uvLoop, &work, [](uv_work_t*) {}, [](uv_work_t *work, int32_t status) {
155 HILOG_DEBUG("Simulator stop uv loop");
156 uv_stop(work->loop);
157 });
158 }
159 }
160
161 panda::JSNApi::StopDebugger(vm_);
162
163 abilities_.clear();
164 nativeEngine_.reset();
165 panda::JSNApi::DestroyJSVM(vm_);
166 vm_ = nullptr;
167 }
168
Initialize(const Options & options)169 bool SimulatorImpl::Initialize(const Options &options)
170 {
171 if (nativeEngine_) {
172 HILOG_DEBUG("Simulator is already initialized");
173 return true;
174 }
175
176 options_ = options;
177 if (!OnInit()) {
178 return false;
179 }
180
181 uv_loop_t *uvLoop = nativeEngine_->GetUVLoop();
182 if (uvLoop == nullptr) {
183 return false;
184 }
185
186 uv_async_init(uvLoop, &debuggerTask_.onPostTaskSignal,
187 reinterpret_cast<uv_async_cb>(DebuggerTask::HandleTask));
188
189 Run();
190 return true;
191 }
192
CallObjectMethod(NativeEngine & engine,NativeValue * value,const char * name,NativeValue * const * argv,size_t argc)193 void CallObjectMethod(NativeEngine &engine, NativeValue *value, const char *name, NativeValue *const *argv, size_t argc)
194 {
195 NativeObject *obj = ConvertNativeValueTo<NativeObject>(value);
196 if (obj == nullptr) {
197 HILOG_ERROR("%{public}s, Failed to get Ability object", __func__);
198 return;
199 }
200
201 NativeValue *methodOnCreate = obj->GetProperty(name);
202 if (methodOnCreate == nullptr) {
203 HILOG_ERROR("Failed to get '%{public}s' from Ability object", name);
204 return;
205 }
206 engine.CallFunction(value, methodOnCreate, argv, argc);
207 }
208
LoadScript(const std::string & srcPath)209 NativeValue *SimulatorImpl::LoadScript(const std::string &srcPath)
210 {
211 panda::Local<panda::ObjectRef> objRef = panda::JSNApi::GetExportObject(vm_, srcPath, "default");
212 if (objRef->IsNull()) {
213 HILOG_ERROR("Get export object failed");
214 return nullptr;
215 }
216
217 auto obj = ArkNativeEngine::ArkValueToNativeValue(static_cast<ArkNativeEngine*>(nativeEngine_.get()), objRef);
218 return nativeEngine_->CreateInstance(obj, nullptr, 0);
219 }
220
StartAbility(const std::string & abilitySrcPath,TerminateCallback callback)221 int64_t SimulatorImpl::StartAbility(const std::string &abilitySrcPath, TerminateCallback callback)
222 {
223 std::ifstream stream(options_.modulePath, std::ios::ate | std::ios::binary);
224 if (!stream.is_open()) {
225 HILOG_ERROR("Failed to open: %{public}s", options_.modulePath.c_str());
226 return -1;
227 }
228
229 size_t len = stream.tellg();
230 std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(len);
231 stream.seekg(0);
232 stream.read(reinterpret_cast<char*>(buffer.get()), len);
233 stream.close();
234
235 auto buf = buffer.release();
236
237 if (stageContext_ == nullptr) {
238 stageContext_ = std::make_shared<AbilityStageContext>();
239 stageContext_->SetOptions(options_);
240 stageContext_->SetConfiguration(options_.configuration);
241 }
242
243 if (!LoadAbilityStage(buf, len)) {
244 HILOG_ERROR("Load ability stage failed.");
245 return -1;
246 }
247
248 abilityPath_ = BUNDLE_INSTALL_PATH + options_.moduleName + "/" + abilitySrcPath;
249 if (!nativeEngine_->RunScriptBuffer(abilityPath_, buf, len, false)) {
250 HILOG_ERROR("Failed to run script: %{public}s", abilityPath_.c_str());
251 return -1;
252 }
253
254 NativeValue *instanceValue = LoadScript(abilityPath_);
255 if (instanceValue == nullptr) {
256 HILOG_ERROR("Failed to create object instance");
257 return -1;
258 }
259
260 ++currentId_;
261 InitResourceMgr();
262 InitJsAbilityContext(instanceValue);
263 DispatchStartLifecycle(instanceValue);
264 abilities_.emplace(currentId_, nativeEngine_->CreateReference(instanceValue, 1));
265
266 return currentId_;
267 }
268
LoadAbilityStage(uint8_t * buffer,size_t len)269 bool SimulatorImpl::LoadAbilityStage(uint8_t *buffer, size_t len)
270 {
271 if (options_.hapModuleInfo.srcEntrance.empty()) {
272 HILOG_DEBUG("module src path is empty.");
273 return true;
274 }
275
276 if (nativeEngine_ == nullptr) {
277 HILOG_ERROR("nativeEngine_ is nullptr");
278 return false;
279 }
280 std::string srcEntrance = options_.hapModuleInfo.srcEntrance;
281 srcEntrance.erase(srcEntrance.rfind("."));
282 srcEntrance.append(".abc");
283 srcEntrance = srcEntrance.substr(srcEntrance.find('/') + 1, srcEntrance.length());
284
285 auto moduleSrcPath = BUNDLE_INSTALL_PATH + options_.moduleName + "/" + srcEntrance;
286 if (!nativeEngine_->RunScriptBuffer(moduleSrcPath, buffer, len, false)) {
287 HILOG_ERROR("Failed to run ability stage script: %{public}s", moduleSrcPath.c_str());
288 return false;
289 }
290
291 NativeValue *instanceValue = LoadScript(moduleSrcPath);
292 if (instanceValue == nullptr) {
293 HILOG_ERROR("Failed to create ability stage instance");
294 return false;
295 }
296
297 InitJsAbilityStageContext(instanceValue);
298
299 CallObjectMethod(*nativeEngine_, instanceValue, "onCreate", nullptr, 0);
300 NativeValue *wantArgv[] = {
301 CreateJsWant(*nativeEngine_)
302 };
303 CallObjectMethod(*nativeEngine_, instanceValue, "onAcceptWant", wantArgv, ArraySize(wantArgv));
304
305 abilityStage_ = std::shared_ptr<NativeReference>(nativeEngine_->CreateReference(instanceValue, 1));
306 return true;
307 }
308
InitJsAbilityStageContext(NativeValue * instanceValue)309 void SimulatorImpl::InitJsAbilityStageContext(NativeValue *instanceValue)
310 {
311 NativeValue *contextObj = CreateJsAbilityStageContext(*nativeEngine_, stageContext_);
312 if (contextObj == nullptr) {
313 HILOG_ERROR("contextObj is nullptr");
314 return;
315 }
316
317 jsStageContext_ = std::shared_ptr<NativeReference>(
318 JsRuntime::LoadSystemModuleByEngine(nativeEngine_.get(), "application.AbilityStageContext", &contextObj, 1));
319 if (jsStageContext_ == nullptr) {
320 HILOG_ERROR("Failed to get LoadSystemModuleByEngine");
321 return;
322 }
323
324 contextObj = jsStageContext_->Get();
325 if (contextObj == nullptr) {
326 HILOG_ERROR("contextObj is nullptr.");
327 return;
328 }
329
330 NativeObject *obj = ConvertNativeValueTo<NativeObject>(instanceValue);
331 if (obj == nullptr) {
332 HILOG_ERROR("obj is nullptr");
333 return;
334 }
335 obj->SetProperty("context", contextObj);
336 }
337
TerminateAbility(int64_t abilityId)338 void SimulatorImpl::TerminateAbility(int64_t abilityId)
339 {
340 if (abilityId == 0 && abilities_.begin() != abilities_.end()) {
341 TerminateAbility(abilities_.begin()->first);
342 return;
343 }
344
345 auto it = abilities_.find(abilityId);
346 if (it == abilities_.end()) {
347 return;
348 }
349
350 std::shared_ptr<NativeReference> ref = it->second;
351 abilities_.erase(it);
352
353 auto instanceValue = ref->Get();
354 if (instanceValue == nullptr) {
355 return;
356 }
357
358 CallObjectMethod(*nativeEngine_, instanceValue, "onBackground", nullptr, 0);
359 CallObjectMethod(*nativeEngine_, instanceValue, "onWindowStageDestroy", nullptr, 0);
360 CallObjectMethod(*nativeEngine_, instanceValue, "onDestroy", nullptr, 0);
361
362 auto windowSceneIter = windowScenes_.find(abilityId);
363 if (windowSceneIter != windowScenes_.end()) {
364 windowScenes_.erase(windowSceneIter);
365 }
366
367 auto windowStageIter = jsWindowStages_.find(abilityId);
368 if (windowStageIter != jsWindowStages_.end()) {
369 jsWindowStages_.erase(windowStageIter);
370 }
371
372 auto jsContextIter = jsContexts_.find(abilityId);
373 if (jsContextIter != jsContexts_.end()) {
374 jsContexts_.erase(jsContextIter);
375 }
376 }
377
UpdateConfiguration(const AppExecFwk::Configuration & config)378 void SimulatorImpl::UpdateConfiguration(const AppExecFwk::Configuration &config)
379 {
380 HILOG_DEBUG("called.");
381 if (abilityStage_ == nullptr) {
382 HILOG_ERROR("abilityStage_ is nullptr");
383 return;
384 }
385
386 auto configuration = std::make_shared<AppExecFwk::Configuration>(config);
387 if (configuration == nullptr) {
388 return;
389 }
390
391 if (stageContext_) {
392 stageContext_->SetConfiguration(configuration);
393 }
394
395 NativeValue *configArgv[] = {
396 CreateJsConfiguration(*nativeEngine_, config)
397 };
398
399 auto abilityStage = abilityStage_->Get();
400 if (abilityStage == nullptr) {
401 HILOG_ERROR("abilityStage is nullptr");
402 return;
403 }
404 CallObjectMethod(*nativeEngine_, abilityStage, "onConfigurationUpdated", configArgv, ArraySize(configArgv));
405 CallObjectMethod(*nativeEngine_, abilityStage, "onConfigurationUpdate", configArgv, ArraySize(configArgv));
406 JsAbilityStageContext::ConfigurationUpdated(nativeEngine_.get(), jsStageContext_, configuration);
407
408 for (auto iter = abilities_.begin(); iter != abilities_.end(); iter++) {
409 auto ability = iter->second->Get();
410 if (ability == nullptr) {
411 HILOG_ERROR("ability is nullptr");
412 continue;
413 }
414
415 CallObjectMethod(*nativeEngine_, ability, "onConfigurationUpdated", configArgv, ArraySize(configArgv));
416 CallObjectMethod(*nativeEngine_, ability, "onConfigurationUpdate", configArgv, ArraySize(configArgv));
417 JsAbilityContext::ConfigurationUpdated(nativeEngine_.get(), iter->second, configuration);
418 }
419 }
420
InitResourceMgr()421 void SimulatorImpl::InitResourceMgr()
422 {
423 HILOG_DEBUG("called.");
424 resourceMgr_ = std::shared_ptr<Global::Resource::ResourceManager>(Global::Resource::CreateResourceManager());
425 if (resourceMgr_ == nullptr) {
426 HILOG_ERROR("resourceMgr is nullptr");
427 return;
428 }
429
430 if (!resourceMgr_->AddResource(options_.resourcePath.c_str())) {
431 HILOG_ERROR("Add resource failed.");
432 }
433 HILOG_DEBUG("Add resource success.");
434 }
435
InitJsAbilityContext(NativeValue * instanceValue)436 void SimulatorImpl::InitJsAbilityContext(NativeValue *instanceValue)
437 {
438 if (context_ == nullptr) {
439 context_ = std::make_shared<AbilityContext>();
440 context_->SetSimulator(static_cast<Simulator*>(this));
441 context_->SetOptions(options_);
442 context_->SetAbilityStageContext(stageContext_);
443 context_->SetResourceManager(resourceMgr_);
444 }
445 NativeValue *contextObj = CreateJsAbilityContext(*nativeEngine_, context_);
446 auto systemModule = std::shared_ptr<NativeReference>(
447 JsRuntime::LoadSystemModuleByEngine(nativeEngine_.get(), "application.AbilityContext", &contextObj, 1));
448 if (systemModule == nullptr) {
449 HILOG_ERROR("systemModule is nullptr.");
450 return;
451 }
452
453 contextObj = systemModule->Get();
454 if (contextObj == nullptr) {
455 HILOG_ERROR("contextObj is nullptr.");
456 return;
457 }
458
459 NativeObject *obj = ConvertNativeValueTo<NativeObject>(instanceValue);
460 if (obj == nullptr) {
461 HILOG_ERROR("obj is nullptr");
462 return;
463 }
464 obj->SetProperty("context", contextObj);
465 jsContexts_.emplace(currentId_, systemModule);
466 }
467
CreateJsWant(NativeEngine & engine)468 NativeValue *SimulatorImpl::CreateJsWant(NativeEngine &engine)
469 {
470 NativeValue *objValue = engine.CreateObject();
471 NativeObject *object = ConvertNativeValueTo<NativeObject>(objValue);
472
473 object->SetProperty("deviceId", CreateJsValue(engine, ""));
474 object->SetProperty("bundleName", CreateJsValue(engine, options_.bundleName));
475 object->SetProperty("abilityName", CreateJsValue(engine, options_.abilityInfo.name));
476 object->SetProperty("moduleName", CreateJsValue(engine, options_.moduleName));
477 object->SetProperty("uri", CreateJsValue(engine, ""));
478 object->SetProperty("type", CreateJsValue(engine, ""));
479 object->SetProperty("flags", CreateJsValue(engine, 0));
480 object->SetProperty("action", CreateJsValue(engine, ""));
481 object->SetProperty("parameters", engine.CreateObject());
482 object->SetProperty("entities", engine.CreateArray(0));
483 return objValue;
484 }
485
CreateJsLaunchParam(NativeEngine & engine)486 NativeValue *SimulatorImpl::CreateJsLaunchParam(NativeEngine &engine)
487 {
488 NativeValue *objValue = engine.CreateObject();
489 NativeObject *object = ConvertNativeValueTo<NativeObject>(objValue);
490 object->SetProperty("launchReason", CreateJsValue(engine, AAFwk::LAUNCHREASON_UNKNOWN));
491 object->SetProperty("lastExitReason", CreateJsValue(engine, AAFwk::LASTEXITREASON_UNKNOWN));
492 return objValue;
493 }
494
DispatchStartLifecycle(NativeValue * instanceValue)495 void SimulatorImpl::DispatchStartLifecycle(NativeValue *instanceValue)
496 {
497 NativeValue *wantArgv[] = {
498 CreateJsWant(*nativeEngine_),
499 CreateJsLaunchParam(*nativeEngine_)
500 };
501 CallObjectMethod(*nativeEngine_, instanceValue, "onCreate", wantArgv, ArraySize(wantArgv));
502
503 auto windowScene = std::make_shared<Rosen::WindowScene>();
504 if (windowScene == nullptr) {
505 return;
506 }
507 sptr<Rosen::IWindowLifeCycle> listener = nullptr;
508 windowScene->Init(-1, context_, listener);
509 auto jsWindowStage = CreateJsWindowStage(windowScene);
510 if (jsWindowStage == nullptr) {
511 return;
512 }
513 NativeValue *argv[] = { jsWindowStage->Get() };
514 CallObjectMethod(*nativeEngine_, instanceValue, "onWindowStageCreate", argv, ArraySize(argv));
515
516 CallObjectMethod(*nativeEngine_, instanceValue, "onForeground", nullptr, 0);
517
518 windowScenes_.emplace(currentId_, windowScene);
519 jsWindowStages_.emplace(currentId_, std::shared_ptr<NativeReference>(jsWindowStage.release()));
520 }
521
CreateJsWindowStage(const std::shared_ptr<Rosen::WindowScene> & windowScene)522 std::unique_ptr<NativeReference> SimulatorImpl::CreateJsWindowStage(
523 const std::shared_ptr<Rosen::WindowScene> &windowScene)
524 {
525 NativeValue *jsWindowStage = Rosen::CreateJsWindowStage(*nativeEngine_, windowScene);
526 if (jsWindowStage == nullptr) {
527 HILOG_ERROR("Failed to create jsWindowSatge object");
528 return nullptr;
529 }
530 return JsRuntime::LoadSystemModuleByEngine(nativeEngine_.get(), "application.WindowStage", &jsWindowStage, 1);
531 }
532
CreateJSVM()533 panda::ecmascript::EcmaVM *SimulatorImpl::CreateJSVM()
534 {
535 panda::RuntimeOption pandaOption;
536 pandaOption.SetArkProperties(DEFAULT_ARK_PROPERTIES);
537 pandaOption.SetGcThreadNum(DEFAULT_GC_THREAD_NUM);
538 pandaOption.SetLongPauseTime(DEFAULT_LONG_PAUSE_TIME);
539 pandaOption.SetGcType(panda::RuntimeOption::GC_TYPE::GEN_GC);
540 pandaOption.SetGcPoolSize(DEFAULT_GC_POOL_SIZE);
541 pandaOption.SetLogLevel(panda::RuntimeOption::LOG_LEVEL::FOLLOW);
542 pandaOption.SetLogBufPrint(PrintVmLog);
543 pandaOption.SetEnableAsmInterpreter(true);
544 pandaOption.SetAsmOpcodeDisableRange("");
545 return panda::JSNApi::CreateJSVM(pandaOption);
546 }
547
OnInit()548 bool SimulatorImpl::OnInit()
549 {
550 vm_ = CreateJSVM();
551 if (vm_ == nullptr) {
552 return false;
553 }
554
555 panda::JSNApi::SetHostResolveBufferTracker(vm_,
556 [](const std::string &inputPath, uint8_t **buff, size_t *buffSize) -> bool {
557 if (inputPath.empty() || buff == nullptr || buffSize == nullptr) {
558 HILOG_ERROR("Param invalid.");
559 return false;
560 }
561
562 HILOG_DEBUG("Get module buffer, input path: %{public}s.", inputPath.c_str());
563 auto data = Ide::StageContext::GetInstance().GetModuleBuffer(inputPath);
564 if (data == nullptr) {
565 HILOG_ERROR("Get module buffer failed, input path: %{public}s.", inputPath.c_str());
566 return false;
567 }
568
569 *buff = data->data();
570 *buffSize = data->size();
571 return true;
572 });
573 panda::JSNApi::DebugOption debugOption = {ARK_DEBUGGER_LIB_PATH, (options_.debugPort != 0), options_.debugPort};
574 panda::JSNApi::StartDebugger(vm_, debugOption, 0,
575 std::bind(&DebuggerTask::OnPostTask, &debuggerTask_, std::placeholders::_1));
576
577 auto nativeEngine = std::make_unique<ArkNativeEngine>(vm_, nullptr);
578
579 NativeObject *globalObj = ConvertNativeValueTo<NativeObject>(nativeEngine->GetGlobal());
580 if (globalObj == nullptr) {
581 HILOG_ERROR("Failed to get global object");
582 return false;
583 }
584
585 InitConsoleLogModule(*nativeEngine, *globalObj);
586 InitTimer(*nativeEngine, *globalObj);
587
588 globalObj->SetProperty("group", nativeEngine->CreateObject());
589
590 uintptr_t bufferStart = reinterpret_cast<uintptr_t>(_binary_jsMockSystemPlugin_abc_start);
591 uintptr_t bufferEnd = reinterpret_cast<uintptr_t>(_binary_jsMockSystemPlugin_abc_end);
592 const uint8_t *buffer = reinterpret_cast<const uint8_t*>(bufferStart);
593 size_t size = bufferEnd - bufferStart;
594
595 panda::JSNApi::Execute(vm_, buffer, size, "_GLOBAL::func_main_0");
596
597 NativeValue *mockRequireNapi = globalObj->GetProperty("requireNapi");
598 globalObj->SetProperty("mockRequireNapi", mockRequireNapi);
599
600 auto* moduleManager = nativeEngine->GetModuleManager();
601 if (moduleManager != nullptr) {
602 HILOG_DEBUG("moduleManager SetPreviewSearchPath: %{public}s", options_.containerSdkPath.c_str());
603 moduleManager->SetPreviewSearchPath(options_.containerSdkPath);
604 }
605
606 std::string fileSeparator = "/";
607 auto pos = options_.containerSdkPath.find(fileSeparator);
608 if (pos == std::string::npos) {
609 fileSeparator = "\\";
610 }
611 std::string fileName = options_.containerSdkPath + fileSeparator + "apiMock" + fileSeparator + "jsMockHmos.abc";
612 HILOG_DEBUG("file name: %{public}s", fileName.c_str());
613 if (!fileName.empty() && AbilityStageContext::Access(fileName)) {
614 panda::JSNApi::Execute(vm_, fileName, "_GLOBAL::func_main_0");
615 }
616
617 const char *moduleName = "SimulatorImpl";
618 BindNativeFunction(*nativeEngine, *globalObj, "requireNapi", moduleName,
619 [](NativeEngine *engine, NativeCallbackInfo *info) {
620 NativeObject *globalObj = ConvertNativeValueTo<NativeObject>(engine->GetGlobal());
621 NativeValue *requireNapi = globalObj->GetProperty("requireNapiPreview");
622
623 NativeValue *result = engine->CallFunction(engine->CreateUndefined(), requireNapi, info->argv, info->argc);
624 if (result->TypeOf() != NATIVE_UNDEFINED) {
625 return result;
626 }
627
628 NativeValue *mockRequireNapi = globalObj->GetProperty("mockRequireNapi");
629 return engine->CallFunction(engine->CreateUndefined(), mockRequireNapi, info->argv, info->argc);
630 });
631
632 panda::JSNApi::SetBundle(vm_, false);
633 panda::JSNApi::SetBundleName(vm_, options_.bundleName);
634 panda::JSNApi::SetModuleName(vm_, options_.moduleName);
635 panda::JSNApi::SetAssetPath(vm_, options_.modulePath);
636
637 nativeEngine_ = std::move(nativeEngine);
638 return true;
639 }
640
Run()641 void SimulatorImpl::Run()
642 {
643 uv_loop_t *uvLoop = nativeEngine_->GetUVLoop();
644 if (uvLoop != nullptr) {
645 uv_run(uvLoop, UV_RUN_NOWAIT);
646 }
647
648 AppExecFwk::EventHandler::PostTask([this]() {
649 Run();
650 });
651 }
652 }
653
Create(const Options & options)654 std::unique_ptr<Simulator> Simulator::Create(const Options &options)
655 {
656 auto simulator = std::make_unique<SimulatorImpl>();
657 if (simulator->Initialize(options)) {
658 return simulator;
659 }
660 return nullptr;
661 }
662 } // namespace AbilityRuntime
663 } // namespace OHOS
664