xref: /ide/tools/previewer/jsapp/lite/JsAppImpl.cpp (revision 7c804472)
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 "JsAppImpl.h"
17
18#include "engines/gfx/gfx_engine_manager.h"
19#include "font/ui_font.h"
20#include "font/ui_font_bitmap.h"
21#include "font/ui_font_header.h"
22#include "font/ui_font_vector.h"
23#include "font/ui_line_break.h"
24#include "font/ui_text_shaping.h"
25#include "gfx_utils/color.h"
26#include "gfx_utils/file.h"
27#include "global.h"
28#include "graphic_startup.h"
29#include "input_device_manager.h"
30#include "js_debugger_config.h"
31#include "product_adapter.h"
32#include "screen_device.h"
33
34#include "AsyncWorkManager.h"
35#include "CommandParser.h"
36#include "CppTimerManager.h"
37#include "FileSystem.h"
38#include "LanguageManagerImpl.h"
39#include "MouseInputImpl.h"
40#include "MouseWheelImpl.h"
41#include "PreviewerEngineLog.h"
42#include "SharedData.h"
43#include "TimerTaskHandler.h"
44#include "TraceTool.h"
45#include "VirtualScreenImpl.h"
46
47using namespace OHOS;
48using namespace ACELite;
49
50static uint8_t g_fontPsramBaseAddr[MIN_FONT_PSRAM_LENGTH];
51
52static void InitVectorFont(UIFont* font, const std::string fontPath)
53{
54    ProductAdapter::SetDefaultFontStyle("SourceHanSansSC-Regular.otf", JsAppImpl::FONT_SIZE_DEFAULT);
55    BaseFont* currentFont = new UIFontVector();
56    if (currentFont == nullptr) {
57        FLOG("InitVectorFont currentFont memory allocation failed");
58        return;
59    }
60    font->SetFont(currentFont);
61    font->SetPsramMemory(reinterpret_cast<uintptr_t>(g_fontPsramBaseAddr), MIN_FONT_PSRAM_LENGTH);
62    int8_t ret = font->SetFontPath(fontPath.data(), BaseFont::DYNAMIC_FONT);
63    if (ret != 0) {
64        ELOG("The vector font path does not exist ! fontPath : %s", fontPath.data());
65        FLOG("InitFontEngine SetFontPath failed. vector fontPath: %s", fontPath.data());
66    }
67    font->RegisterFontInfo("SourceHanSansSC-Regular.otf");
68    font->SetCurrentLangId(0);
69}
70
71static void InitFontEngine()
72{
73    UIFont* font = UIFont::GetInstance();
74    if (font == nullptr) {
75        ELOG("InitFontEngine:font is nullptr");
76        return;
77    }
78    std::string deviceType = CommandParser::GetInstance().GetDeviceType();
79    std::string separator = FileSystem::GetSeparator();
80    std::string fontPath = FileSystem::GetApplicationPath() + separator + ".." + separator + "config" + separator;
81    InitVectorFont(font, fontPath);
82
83    int32_t fp = 0;
84    std::string fileName = fontPath + "line_cj.brk";
85#ifdef _WIN32
86    fp = open(fileName.c_str(), O_RDONLY | O_BINARY);
87#else
88    fp = open(fileName.c_str(), O_RDONLY);
89#endif
90    if (fp < 0) {
91        ELOG("Open font path failed.");
92        return;
93    }
94    uint32_t lineBrkSize = lseek(fp, 0, SEEK_END);
95    lseek(fp, 0, SEEK_SET);
96    UILineBreakEngine& lbEngine = UILineBreakEngine::GetInstance();
97    lbEngine.SetRuleBinInfo(fp, 0, lineBrkSize);
98    lbEngine.Init();
99}
100
101static void InitHalScreen()
102{
103    InputDeviceManager::GetInstance()->Add(&MouseInputImpl::GetInstance());
104    InputDeviceManager::GetInstance()->Add(&MouseWheelImpl::GetInstance());
105}
106
107JsAppImpl::JsAppImpl()
108    : isInterrupt(false),
109      taskHandleTimer(nullptr),
110      deviceCheckTimer(nullptr),
111      jsCheckTimer(nullptr),
112      jsAbility(nullptr),
113      jsThread(nullptr)
114{
115}
116
117JsAppImpl::~JsAppImpl() {}
118
119JsAppImpl& JsAppImpl::GetInstance()
120{
121    static JsAppImpl instance;
122    return instance;
123}
124
125void JsAppImpl::Start()
126{
127    isFinished = false;
128    isInterrupt = false;
129    jsThread = std::make_unique<std::thread>([this]() {
130        this->ThreadCallBack();
131    });
132    if (jsThread == nullptr) {
133        ELOG("JsApp::Start jsThread memory allocation failed");
134    }
135    jsThread->detach();
136}
137
138void JsAppImpl::Restart()
139{
140    Stop();
141    Start();
142}
143
144void JsAppImpl::Interrupt()
145{
146    AsyncWorkManager::GetInstance().ClearAllAsyncWork();
147    jsAbility->Hide();
148    jsAbility->TransferToDestroy();
149    jsAbility.reset();
150    isFinished = true;
151    isInterrupt = true;
152    ILOG("JsAppImpl::ThreadCallBack finished");
153}
154
155void JsAppImpl::ThreadCallBack()
156{
157    OHOS::GraphicStartUp::Init();
158    GLOBAL_ConfigLanguage(SharedData<std::string>::GetData(SharedDataType::LANGUAGE).data());
159    InitHalScreen();
160    InitFontEngine();
161    VirtualScreenImpl::GetInstance().InitAll(pipeName, pipePort);
162    StartJsApp();
163    InitTimer();
164
165    std::thread::id curThreadId = std::this_thread::get_id();
166#if defined(LITEWEARABLE_SUPPORTED) && LITEWEARABLE_SUPPORTED
167    SharedData<uint8_t>::AppendNotify(SharedDataType::HEARTBEAT_VALUE, TimerTaskHandler::CheckHeartRateChanged,
168        curThreadId, 50); // Duration:50 x 100 ms
169    SharedData<uint32_t>::AppendNotify(SharedDataType::PRESSURE_VALUE, TimerTaskHandler::CheckBarometerChanged,
170        curThreadId);
171    SharedData<uint32_t>::AppendNotify(SharedDataType::SUMSTEP_VALUE, TimerTaskHandler::CheckStepCountChanged,
172        curThreadId);
173    SharedData<bool>::AppendNotify(SharedDataType::WEARING_STATE, TimerTaskHandler::CheckOnBodyStateChanged,
174        curThreadId);
175#endif
176    SharedData<std::string>::AppendNotify(SharedDataType::LANGUAGE, TimerTaskHandler::CheckLanguageChanged,
177        curThreadId);
178
179    CppTimerManager& manager = CppTimerManager::GetTimerManager();
180    while (!isInterrupt) {
181        std::this_thread::sleep_for(std::chrono::milliseconds(1));
182        manager.RunTimerTick();
183    }
184}
185
186void JsAppImpl::InitTimer()
187{
188    taskHandleTimer = std::make_unique<CppTimer>(TimerTaskHandler::TaskHandle);
189    if (taskHandleTimer == nullptr) {
190        ELOG("JsApp::InitTimer taskHandleTimer memory allocation failed.");
191        return;
192    }
193    CppTimerManager::GetTimerManager().AddCppTimer(*taskHandleTimer);
194    taskHandleTimer->Start(TASK_HANDLE_TIMER_INTERVAL);
195
196    deviceCheckTimer = std::make_unique<CppTimer>(TimerTaskHandler::CheckDevice);
197    if (deviceCheckTimer == nullptr) {
198        ELOG("JsApp::InitTimer deviceCheckTimer memory allocation failed.");
199        return;
200    }
201    CppTimerManager::GetTimerManager().AddCppTimer(*deviceCheckTimer);
202    deviceCheckTimer->Start(DEVICE_CHECK_TIMER_INTERVAL);
203
204    jsCheckTimer = std::make_unique<CppTimer>(TimerTaskHandler::CheckJsRunning);
205    if (jsCheckTimer == nullptr) {
206        ELOG("JsApp::InitTimer jsCheckTimer memory allocation failed.");
207        return;
208    }
209    CppTimerManager::GetTimerManager().AddCppTimer(*jsCheckTimer);
210    jsCheckTimer->Start(JS_CHECK_TIMER_INTERVAL);
211}
212
213void JsAppImpl::StartJsApp()
214{
215    if (jsAbility != nullptr) {
216        FLOG("JsApp::StartJsApp jsAbility is not null.");
217        return;
218    }
219
220    jsAbility = std::make_unique<OHOS::ACELite::JSAbility>();
221    if (jsAbility == nullptr) {
222        FLOG("JsApp::StartJsApp jsAbility memory allocation failed");
223        return;
224    }
225
226    DebuggerConfig config;
227    config.startDebuggerServer = isDebug;
228    ILOG("Launch JS APP.");
229    ILOG("Debug Server Enable: %d", config.startDebuggerServer);
230    config.snapshotMode = false;
231    config.heapSize = jsHeapSize;
232    if (isDebug && debugServerPort) {
233        config.port = debugServerPort;
234        config.startDebuggerServer = isDebug;
235        config.snapshotMode = false;
236        ILOG("Debug Server Port: %d", debugServerPort);
237    }
238    Debugger::GetInstance().ConfigEngineDebugger(config);
239    ILOG("Launch Js app");
240    TraceTool::GetInstance().HandleTrace("Launch Js app");
241    if (urlPath.empty()) {
242        jsAbility->Launch(jsAppPath.c_str(), bundleName.c_str(), 0);
243        jsAbility->Show();
244        ILOG("JsApp::StartJsApp launch finished.");
245        return;
246    }
247    Json2::Value val = JsonReader::CreateObject();
248    val.Add("uri", urlPath.c_str());
249    std::string routerInfo = val.ToStyledString();
250    jsAbility->Launch(jsAppPath.c_str(), bundleName.c_str(), 0, routerInfo.data());
251    jsAbility->Show();
252    ILOG("JsApp::StartJsApp launch with single page mode finished.");
253    isFinished = false;
254}
255
256void JsAppImpl::InitJsApp()
257{
258    CommandParser& parser = CommandParser::GetInstance();
259    // Initialize Image Pipeline Name
260    if (parser.IsSet("s")) {
261        SetPipeName(parser.Value("s"));
262    }
263    if (parser.IsSet("lws")) {
264        SetPipePort(parser.Value("lws"));
265    }
266    // Set the application name.
267    SetBundleName(parser.GetAppName());
268    // Processing JSheap
269    SetJSHeapSize(parser.GetJsHeapSize());
270    // Start JSApp
271    if (!parser.IsSet("t")) {
272        if (parser.IsSet("d")) {
273            SetIsDebug(true);
274            if (parser.IsSet("p")) {
275                SetDebugServerPort(static_cast<uint16_t>(atoi(parser.Value("p").c_str())));
276            }
277        }
278        SetJsAppPath(parser.Value("j"));
279        if (parser.IsSet("url")) {
280            SetUrlPath(parser.Value("url"));
281        }
282        Start();
283    }
284}
285