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