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