1 /*
2 * Copyright (c) 2020-2021 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 "js_ability.h"
17
18 #include <cstring>
19 #include "ace_event_error_code.h"
20 #include "ace_log.h"
21 #include "acelite_config.h"
22 #include "async_task_manager.h"
23 #if (OHOS_ACELITE_PRODUCT_WATCH == 1)
24 #include "dft_impl.h"
25 #endif // OHOS_ACELITE_PRODUCT_WATCH
26 #include "fatal_handler.h"
27 #include "js_ability_impl.h"
28 #include "js_async_work.h"
29 #include "js_profiler.h"
30 #include "product_adapter.h"
31 #if (defined(__LINUX__) || defined(__LITEOS_A__))
32 #include "ace_ability.h"
33 #endif
34 #include "module_manager.h"
35
36 namespace OHOS {
37 namespace ACELite {
38 /**
39 * This is a helper function to cast void* to JSAbilityImpl*, for header separating purpose.
40 */
CastAbilityImpl(void * abilityImpl)41 static JSAbilityImpl *CastAbilityImpl(void *abilityImpl)
42 {
43 if (abilityImpl == nullptr) {
44 return nullptr;
45 }
46
47 return static_cast<JSAbilityImpl *>(abilityImpl);
48 }
49
DumpNativeMemoryUsage()50 static void DumpNativeMemoryUsage()
51 {
52 #if (OHOS_ACELITE_PRODUCT_WATCH == 1)
53 NativeMemInfo memInfo;
54 ProductAdapter::GetNativeMemInfo(&memInfo);
55 HILOG_DEBUG(HILOG_MODULE_ACE, "available free size: %{public}d", memInfo.freeSize);
56 #endif // OHOS_ACELITE_PRODUCT_WATCH
57 }
58
~JSAbility()59 JSAbility::~JSAbility()
60 {
61 // check the status
62 if (jsAbilityImpl_ != nullptr) {
63 // the JSAbility instance can only be destroied after transfering the app to DESTROY state
64 ProductAdapter::RestoreSystemWrapper("AMS is deleting app task but without normal lifecycle transition!");
65 }
66 }
67
Launch(const char * const abilityPath,const char * const bundleName,uint16_t token,const char * pageInfo)68 void JSAbility::Launch(const char * const abilityPath, const char * const bundleName, uint16_t token,
69 const char *pageInfo)
70 {
71 if (jsAbilityImpl_ != nullptr) {
72 HILOG_ERROR(HILOG_MODULE_ACE, "Launch only can be triggered once");
73 ACE_ERROR_CODE_PRINT(EXCE_ACE_FWK_LAUNCH_FAILED, EXCE_ACE_APP_ALREADY_LAUNCHED);
74 return;
75 }
76
77 if ((abilityPath == nullptr) || (strlen(abilityPath) == 0)) {
78 HILOG_ERROR(HILOG_MODULE_ACE, "invalid app path");
79 ACE_ERROR_CODE_PRINT(EXCE_ACE_FWK_LAUNCH_FAILED, EXCE_ACE_INVALID_APP_PATH);
80 return;
81 }
82
83 if ((bundleName == nullptr) || (strlen(bundleName) == 0)) {
84 HILOG_ERROR(HILOG_MODULE_ACE, "invalid bundle name");
85 ACE_ERROR_CODE_PRINT(EXCE_ACE_FWK_LAUNCH_FAILED, EXCE_ACE_INVALID_BUNDLE_NAME);
86 return;
87 }
88
89 HILOG_INFO(HILOG_MODULE_ACE, "LIFECYCLE: JS Ability is launching");
90
91 #if (MOCK_JS_ASYNC_WORK != 1)
92 JsAsyncWork::SetFatalHandleFunc(FatalHandler::IsErrorHittedWrapper, FatalHandler::IsAppExitingWrapper);
93 #endif
94 #if (defined(__LINUX__) || defined(__LITEOS_A__))
95 JsAsyncWork::SetPostUITaskFunc(AceAbility::PostUITask);
96 #endif
97 ModuleManager::GetInstance()->SetBundleNameGetter(JSAbility::GetPackageName);
98 DumpNativeMemoryUsage();
99 jsAbilityImpl_ = new JSAbilityImpl();
100 if (jsAbilityImpl_ == nullptr) {
101 HILOG_ERROR(HILOG_MODULE_ACE, "Create JSAbilityRuntime failed");
102 return;
103 }
104 START_TRACING(LAUNCH);
105 // mark the flag in advance to make sure we can take over render tick as soon as possible
106 ProductAdapter::UpdateRenderTickAcceptable(true);
107 JSAbilityImpl *jsAbilityImpl = CastAbilityImpl(jsAbilityImpl_);
108 #if (MOCK_JS_ASYNC_WORK != 1)
109 // simulator uses the self-implementation for async work, this interface is not included
110 JsAsyncWork::SetEnvStatus(true);
111 #endif
112 jsAbilityImpl->InitEnvironment(abilityPath, bundleName, token);
113 ACE_EVENT_PRINT(MT_ACE_FWK_LAUNCHING, 0);
114 FatalHandler::GetInstance().RegisterFatalHandler(this);
115 #ifdef _MINI_MULTI_TASKS_
116 jsAbilityImpl->DeliverCreate();
117 #else
118 jsAbilityImpl->DeliverCreate(pageInfo);
119 #endif
120 ProductAdapter::UpdateDefaultFont();
121 STOP_TRACING();
122 OUTPUT_TRACE();
123 }
124
125 #ifdef _MINI_MULTI_TASKS_
OnRestoreData(AbilitySlite::AbilitySavedData * data)126 void JSAbility::OnRestoreData(AbilitySlite::AbilitySavedData *data)
127 {
128 if (jsAbilityImpl_ == nullptr) {
129 HILOG_ERROR(HILOG_MODULE_ACE, "Must trigger Launch first");
130 return;
131 }
132 JSAbilityImpl *jsAbilityImpl = CastAbilityImpl(jsAbilityImpl_);
133 jsAbilityImpl->OnRestoreData(data);
134 }
135 #endif
136
Show()137 void JSAbility::Show()
138 {
139 if (jsAbilityImpl_ == nullptr) {
140 HILOG_ERROR(HILOG_MODULE_ACE, "Must trigger Launch first");
141 return;
142 }
143
144 HILOG_INFO(HILOG_MODULE_ACE, "LIFECYCLE: JS Ability will be shown");
145 ACE_EVENT_PRINT(MT_ACE_FWK_ACTIVING, 0);
146 FatalHandler::GetInstance().SetExitingFlag(false);
147 JSAbilityImpl *jsAbilityImpl = CastAbilityImpl(jsAbilityImpl_);
148 jsAbilityImpl->Show();
149 AsyncTaskManager::GetInstance().SetFront(true);
150 ProductAdapter::UpdateRenderTickAcceptable(true);
151 isActived_ = true;
152 }
153
Hide()154 void JSAbility::Hide()
155 {
156 if (jsAbilityImpl_ == nullptr) {
157 HILOG_ERROR(HILOG_MODULE_ACE, "Must trigger Launch first");
158 return;
159 }
160 HILOG_INFO(HILOG_MODULE_ACE, "LIFECYCLE: JS Ability will be hidden");
161 ACE_EVENT_PRINT(MT_ACE_FWK_HIDING, 0);
162 JSAbilityImpl *jsAbilityImpl = CastAbilityImpl(jsAbilityImpl_);
163 jsAbilityImpl->Hide();
164 AsyncTaskManager::GetInstance().SetFront(false);
165 ProductAdapter::UpdateRenderTickAcceptable(false);
166 isActived_ = false;
167 }
168
169 #ifdef _MINI_MULTI_TASKS_
OnSaveData(AbilitySlite::AbilitySavedData * data)170 void JSAbility::OnSaveData(AbilitySlite::AbilitySavedData *data)
171 {
172 if (jsAbilityImpl_ == nullptr) {
173 HILOG_ERROR(HILOG_MODULE_ACE, "Must trigger Launch first");
174 return;
175 }
176 JSAbilityImpl *jsAbilityImpl = CastAbilityImpl(jsAbilityImpl_);
177 jsAbilityImpl->OnSaveData(data);
178 }
179 #endif
180
TransferToDestroy()181 void JSAbility::TransferToDestroy()
182 {
183 if (jsAbilityImpl_ == nullptr) {
184 HILOG_ERROR(HILOG_MODULE_ACE, "Must trigger Launch first");
185 return;
186 }
187
188 #if (MOCK_JS_ASYNC_WORK != 1)
189 // simulator uses the self-implementation for async work, this interface is not included
190 JsAsyncWork::SetEnvStatus(false);
191 #endif
192 HILOG_INFO(HILOG_MODULE_ACE, "LIFECYCLE: JS Ability is exiting");
193 ACE_EVENT_PRINT(MT_ACE_FWK_DESTROYING, 0);
194 JSAbilityImpl *jsAbilityImpl = CastAbilityImpl(jsAbilityImpl_);
195 jsAbilityImpl->CleanUp();
196 // Reset render flag or low layer task mutex in case we are during the rendering process,
197 // this situation might happen if the destroy function is called outside of JS thread, such as AMS.
198 ProductAdapter::UpdateRenderTickAcceptable(false);
199 FatalHandler::GetInstance().ResetRendering();
200 FatalHandler::GetInstance().SetExitingFlag(false);
201 #if (FEATURE_SCREEN_ON_VISIBLE == 1)
202 if (ProductAdapter::SetScreenOnVisible(false) == false) {
203 HILOG_ERROR(HILOG_MODULE_ACE, "Fail to recover screen visible property");
204 }
205 #endif
206 #if (OHOS_ACELITE_PRODUCT_WATCH == 1)
207 JsAsyncWork::SetAppQueueHandler(nullptr);
208 DftImpl::GetInstance()->RegisterPageReplaced(nullptr);
209 #endif // OHOS_ACELITE_PRODUCT_WATCH
210 delete reinterpret_cast<JSAbilityImpl *>(jsAbilityImpl_);
211 jsAbilityImpl_ = nullptr;
212 DumpNativeMemoryUsage();
213 }
214
BackPressed()215 void JSAbility::BackPressed()
216 {
217 if (jsAbilityImpl_ == nullptr) {
218 HILOG_ERROR(HILOG_MODULE_ACE, "Must trigger Launch first");
219 return;
220 }
221
222 JSAbilityImpl *jsAbilityImpl = CastAbilityImpl(jsAbilityImpl_);
223 jsAbilityImpl->NotifyBackPressed();
224 }
225
GetPackageName()226 const char *JSAbility::GetPackageName()
227 {
228 return JsAppContext::GetInstance()->GetCurrentBundleName();
229 }
230
231 // this public interface will be deprecated, only fatal scenario can trigger force destroy
ForceDestroy()232 void JSAbility::ForceDestroy()
233 {
234 HILOG_ERROR(HILOG_MODULE_ACE, "ForceDestroy interface is deprecated as JS engine can not run on other task");
235 }
236
IsRecycled()237 bool JSAbility::IsRecycled()
238 {
239 return (jsAbilityImpl_ == nullptr);
240 }
241
GetLazyLoadManager()242 LazyLoadManager *GetLazyLoadManager()
243 {
244 JsAppContext *context = JsAppContext::GetInstance();
245 return const_cast<LazyLoadManager *>(context->GetLazyLoadManager());
246 }
247
GetLazyLoadManagerState()248 LazyLoadState GetLazyLoadManagerState()
249 {
250 LazyLoadManager *lazyLoadManager = GetLazyLoadManager();
251 return lazyLoadManager->GetState();
252 }
253
LazyLoadHandleRenderTick(void * data)254 void JSAbility::LazyLoadHandleRenderTick(void *data)
255 {
256 UNUSED(data);
257 // double check, if state reseted, break
258 LazyLoadState state = GetLazyLoadManagerState();
259 if (state == LazyLoadState::INIT || state == LazyLoadState::DONE) {
260 return;
261 }
262
263 GetLazyLoadManager()->RenderLazyLoadWatcher();
264 }
265
HandleRenderTick()266 void JSAbility::HandleRenderTick()
267 {
268 if (!isActived_) {
269 // skip the TE tick if we are not foreground
270 ProductAdapter::NotifyRenderEnd();
271 errorTickCount_++;
272 if ((errorTickCount_ % ERR_TICK_COUNT_TRACE_CTRL) == 1) {
273 HILOG_WARN(HILOG_MODULE_ACE, "skip one render tick process since not activated, count[%{public}d]",
274 errorTickCount_);
275 }
276 if (errorTickCount_ == UINT32_MAX) {
277 errorTickCount_ = 0;
278 }
279 return;
280 }
281
282 // reset error tick tracing count
283 errorTickCount_ = 0;
284 if ((ProductAdapter::IsTEHandlersRegisted()) && !(FatalHandler::GetInstance().IsAppExiting())) {
285 FatalHandler::GetInstance().SetTEHandlingFlag(true);
286 ProductAdapter::ProcessOneTE();
287 // check if state is ready
288 if (GetLazyLoadManagerState() == LazyLoadState::READY) {
289 JsAsyncWork::DispatchAsyncWork(LazyLoadHandleRenderTick, nullptr);
290 }
291 FatalHandler::GetInstance().SetTEHandlingFlag(false);
292 }
293 }
294 } // namespace ACELite
295 } // namespace OHOS
296