1 /*
2 * Copyright (c) 2020 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 "ability_service.h"
17 #include "aafwk_event_error_id.h"
18 #include "aafwk_event_error_code.h"
19 #include "ability_errors.h"
20 #include "ability_list.h"
21 #include "ability_message_id.h"
22 #include "ability_mgr_service.h"
23 #include "ability_mgr_slite_feature.h"
24 #include "ability_record.h"
25 #include "ability_stack.h"
26 #include "ability_state.h"
27 #include "abilityms_log.h"
28 #include "ability_manager_inner.h"
29 #include "bundle_manager.h"
30 #include "cmsis_os.h"
31 #ifdef OHOS_DMS_ENABLED
32 #include "dmsfwk_interface.h"
33 #endif
34 #include "js_app_host.h"
35 #include "los_task.h"
36 #include "pms.h"
37 #ifdef OHOS_DMS_ENABLED
38 #include "samgr_lite.h"
39 #endif
40 #include "slite_ability.h"
41 #include "utils.h"
42 #include "want.h"
43
44 using namespace OHOS::ACELite;
45
46 namespace OHOS {
47 constexpr char LAUNCHER_BUNDLE_NAME[] = "com.huawei.launcher";
48 constexpr uint16_t LAUNCHER_TOKEN = 0;
49 constexpr int32_t QUEUE_LENGTH = 32;
50 constexpr int32_t APP_TASK_PRI = 25;
51
AbilityService()52 AbilityService::AbilityService()
53 {
54 }
55
~AbilityService()56 AbilityService::~AbilityService()
57 {
58 DeleteRecordInfo(LAUNCHER_TOKEN);
59 }
60
StartLauncher()61 void AbilityService::StartLauncher()
62 {
63 auto record = new AbilityRecord();
64 record->SetAppName(LAUNCHER_BUNDLE_NAME);
65 record->SetToken(LAUNCHER_TOKEN);
66 record->SetState(SCHEDULE_ACTIVE);
67 record->SetTaskId(LOS_CurTaskIDGet());
68 abilityList_.Add(record);
69 abilityStack_.PushAbility(record);
70 (void) SchedulerLifecycleInner(record, STATE_ACTIVE);
71 }
72
CleanWant()73 void AbilityService::CleanWant()
74 {
75 ClearWant(want_);
76 AdapterFree(want_);
77 }
78
IsValidAbility(AbilityInfo * abilityInfo)79 bool AbilityService::IsValidAbility(AbilityInfo *abilityInfo)
80 {
81 if (abilityInfo == nullptr) {
82 return false;
83 }
84 if (abilityInfo->bundleName == nullptr || abilityInfo->srcPath == nullptr) {
85 return false;
86 }
87 if (strlen(abilityInfo->bundleName) == 0 || strlen(abilityInfo->srcPath) == 0) {
88 return false;
89 }
90 return true;
91 }
92
StartRemoteAbility(const Want * want)93 int32_t AbilityService::StartRemoteAbility(const Want *want)
94 {
95 #ifdef OHOS_DMS_ENABLED
96 IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(DISTRIBUTED_SCHEDULE_SERVICE, DMSLITE_FEATURE);
97 if (iUnknown == nullptr) {
98 HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to get distributed schedule service.");
99 return EC_INVALID;
100 }
101 DmsProxy *dmsInterface = nullptr;
102 int32_t retVal = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **) &dmsInterface);
103 if (retVal != EC_SUCCESS) {
104 HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to get DMS interface retVal: [%{public}d]", retVal);
105 return EC_INVALID;
106 }
107 AbilityRecord *record = abilityList_.GetByTaskId(curTask_);
108 if (record == nullptr) {
109 HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to get record by taskId.");
110 return PARAM_NULL_ERROR;
111 }
112 const char *callerBundleName = record->GetAppName();
113 if (callerBundleName == nullptr) {
114 HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to get callerBundleName.");
115 return PARAM_NULL_ERROR;
116 }
117
118 CallerInfo callerInfo = {
119 .uid = 0,
120 .bundleName = OHOS::Utils::Strdup(callerBundleName)
121 };
122 retVal = dmsInterface->StartRemoteAbility(want, &callerInfo, nullptr);
123
124 HILOG_INFO(HILOG_MODULE_AAFWK, "StartRemoteAbility retVal: [%{public}d]", retVal);
125 AdapterFree(callerInfo.bundleName);
126 return retVal;
127 #else
128 return PARAM_NULL_ERROR;
129 #endif
130 }
131
StartAbility(const Want * want)132 int32_t AbilityService::StartAbility(const Want *want)
133 {
134 if (want == nullptr || want->element == nullptr) {
135 HILOG_ERROR(HILOG_MODULE_AAFWK, "Ability Service wanted element is null");
136 return PARAM_NULL_ERROR;
137 }
138 char *bundleName = want->element->bundleName;
139 if (bundleName == nullptr) {
140 HILOG_ERROR(HILOG_MODULE_AAFWK, "Ability Service wanted bundleName is null");
141 return PARAM_NULL_ERROR;
142 }
143
144 #ifdef OHOS_DMS_ENABLED
145 if (want->element->deviceId != nullptr && *(want->element->deviceId) != '\0') {
146 // deviceId is set
147 return StartRemoteAbility(want);
148 }
149 #endif
150
151 AbilitySvcInfo *info =
152 static_cast<OHOS::AbilitySvcInfo *>(AdapterMalloc(sizeof(AbilitySvcInfo)));
153 if (info == nullptr) {
154 HILOG_ERROR(HILOG_MODULE_AAFWK, "Ability Service AbilitySvcInfo is null");
155 return PARAM_NULL_ERROR;
156 }
157
158 if (strcmp(bundleName, LAUNCHER_BUNDLE_NAME) == 0) {
159 // Launcher
160 info->bundleName = Utils::Strdup(bundleName);
161 info->path = nullptr;
162 } else {
163 // JS APP
164 #if ((defined OHOS_APPEXECFWK_BMS_BUNDLEMANAGER) || (defined APP_PLATFORM_WATCHGT))
165 AbilityInfo abilityInfo = { nullptr, nullptr };
166 QueryAbilityInfo(want, &abilityInfo);
167 if (!IsValidAbility(&abilityInfo)) {
168 APP_ERRCODE_EXTRA(EXCE_ACE_APP_START, EXCE_ACE_APP_START_UNKNOWN_BUNDLE_INFO);
169 ClearAbilityInfo(&abilityInfo);
170 AdapterFree(info);
171 HILOG_ERROR(HILOG_MODULE_AAFWK, "Ability Service returned bundleInfo is not valid");
172 return PARAM_NULL_ERROR;
173 }
174 info->bundleName = OHOS::Utils::Strdup(abilityInfo.bundleName);
175 info->path = OHOS::Utils::Strdup(abilityInfo.srcPath);
176 ClearAbilityInfo(&abilityInfo);
177 #else
178 info->bundleName = Utils::Strdup(bundleName);
179 // Here users assign want->data with js app path.
180 info->path = Utils::Strdup((const char *)want->data);
181 #endif
182 }
183
184 info->data = OHOS::Utils::Memdup(want->data, want->dataLength);
185 info->dataLength = want->dataLength;
186 auto ret = StartAbility(info);
187 AdapterFree(info->bundleName);
188 AdapterFree(info->path);
189 AdapterFree(info->data);
190 AdapterFree(info);
191 return ERR_OK;
192 }
193
UpdateRecord(AbilitySvcInfo * info)194 void AbilityService::UpdateRecord(AbilitySvcInfo *info)
195 {
196 if (info == nullptr) {
197 return;
198 }
199 AbilityRecord *record = abilityList_.Get(info->bundleName);
200 if (record == nullptr) {
201 return;
202 }
203 if (record->GetToken() != LAUNCHER_TOKEN) {
204 return;
205 }
206 record->SetAppData(info->data, info->dataLength);
207 }
208
StartAbility(AbilitySvcInfo * info)209 int32_t AbilityService::StartAbility(AbilitySvcInfo *info)
210 {
211 if ((info == nullptr) || (info->bundleName == nullptr) || (strlen(info->bundleName) == 0)) {
212 return PARAM_NULL_ERROR;
213 }
214 HILOG_INFO(HILOG_MODULE_AAFWK, "StartAbility");
215
216 auto topRecord = abilityStack_.GetTopAbility();
217 if ((topRecord == nullptr) || (topRecord->GetAppName() == nullptr)) {
218 HILOG_ERROR(HILOG_MODULE_AAFWK, "StartAbility top null.");
219 return PARAM_NULL_ERROR;
220 }
221 uint16_t topToken = topRecord->GetToken();
222 // start launcher
223 if (strcmp(info->bundleName, LAUNCHER_BUNDLE_NAME) == 0) {
224 UpdateRecord(info);
225 if (topToken != LAUNCHER_TOKEN && topRecord->GetState() != SCHEDULE_BACKGROUND) {
226 HILOG_INFO(HILOG_MODULE_AAFWK, "Change Js app to background.");
227 (void) SchedulerLifecycleInner(topRecord, STATE_BACKGROUND);
228 } else {
229 (void) SchedulerLifecycle(LAUNCHER_TOKEN, STATE_ACTIVE);
230 }
231 return ERR_OK;
232 }
233
234 if (!CheckResponse(info->bundleName)) {
235 return PARAM_CHECK_ERROR;
236 }
237
238 // start js app
239 if (topRecord->IsAttached() && topRecord->GetToken() != LAUNCHER_TOKEN) {
240 // start app is top
241 if (strcmp(info->bundleName, topRecord->GetAppName()) == 0) {
242 if (topRecord->GetState() == SCHEDULE_BACKGROUND) {
243 HILOG_INFO(HILOG_MODULE_AAFWK, "StartAbility Resume app when background.");
244 (void) SchedulerLifecycle(LAUNCHER_TOKEN, STATE_BACKGROUND);
245 return ERR_OK;
246 }
247 HILOG_INFO(HILOG_MODULE_AAFWK, "Js app already started or starting.");
248 } else {
249 // js to js
250 HILOG_INFO(HILOG_MODULE_AAFWK, "Terminate pre js app when js to js");
251 TerminateAbility(topRecord->GetToken());
252 pendingToken_ = GenerateToken();
253 }
254 }
255
256 // application has not been launched and then to check priority and permission.
257 return PreCheckStartAbility(info->bundleName, info->path, info->data, info->dataLength);
258 }
259
TerminateAbility(uint16_t token)260 int32_t AbilityService::TerminateAbility(uint16_t token)
261 {
262 HILOG_INFO(HILOG_MODULE_AAFWK, "TerminateAbility [%{public}u]", token);
263 AbilityRecord *topRecord = const_cast<AbilityRecord *>(abilityStack_.GetTopAbility());
264 if (topRecord == nullptr) {
265 APP_ERRCODE_EXTRA(EXCE_ACE_APP_START, EXCE_ACE_APP_STOP_NO_ABILITY_RUNNING);
266 return PARAM_NULL_ERROR;
267 }
268 uint16_t topToken = topRecord->GetToken();
269 if (token == LAUNCHER_TOKEN) {
270 // if js is in background, the launcher goes back to background and js goes to active
271 if (topToken != token && topRecord->GetState() == SCHEDULE_BACKGROUND) {
272 HILOG_INFO(HILOG_MODULE_AAFWK, "Resume Js app [%{public}u]", topToken);
273 return SchedulerLifecycle(LAUNCHER_TOKEN, STATE_BACKGROUND);
274 }
275 return ERR_OK;
276 }
277
278 if (token != topToken) {
279 APP_ERRCODE_EXTRA(EXCE_ACE_APP_START, EXCE_ACE_APP_STOP_UNKNOWN_ABILITY_TOKEN);
280 DeleteRecordInfo(token);
281 return -1;
282 }
283 topRecord->SetTerminated(true);
284 // TerminateAbility top js
285 return SchedulerLifecycleInner(topRecord, STATE_BACKGROUND);
286 }
287
ForceStopBundle(uint16_t token)288 int32_t AbilityService::ForceStopBundle(uint16_t token)
289 {
290 HILOG_INFO(HILOG_MODULE_AAFWK, "ForceStopBundle [%{public}u]", token);
291 if (token == LAUNCHER_TOKEN) {
292 HILOG_INFO(HILOG_MODULE_AAFWK, "Launcher does not support force stop.");
293 return ERR_OK;
294 }
295
296 // free js mem and delete the record
297 if (ForceStopBundleInner(token) != ERR_OK) {
298 return PARAM_CHECK_ERROR;
299 }
300
301 // active the launcher
302 AbilityRecord *launcherRecord = abilityList_.Get(LAUNCHER_TOKEN);
303 if (launcherRecord == nullptr) {
304 return PARAM_NULL_ERROR;
305 }
306 if (launcherRecord->GetState() != SCHEDULE_ACTIVE) {
307 return SchedulerLifecycle(LAUNCHER_TOKEN, STATE_ACTIVE);
308 }
309 return ERR_OK;
310 }
311
ForceStop(char * bundleName)312 int32_t AbilityService::ForceStop(char* bundleName)
313 {
314 // stop Launcher
315 if (strcmp(bundleName, LAUNCHER_BUNDLE_NAME) == 0) {
316 return TerminateAbility(0);
317 }
318
319 // stop js app
320 if (strcmp(abilityStack_.GetTopAbility()->GetAppName(), bundleName) == 0) {
321 AbilityRecord *topRecord = const_cast<AbilityRecord *>(abilityStack_.GetTopAbility());
322 HILOG_INFO(HILOG_MODULE_AAFWK, "ForceStop [%{public}u]", topRecord->GetToken());
323 return TerminateAbility(topRecord->GetToken());
324 #ifndef __LITEOS_M__
325 } else {
326 uint16_t size = abilityStack_.GetAllAbilities();
327 HILOG_INFO(HILOG_MODULE_AAFWK, "ForceStop innerStack number is [%{public}u]", size);
328 // topAbility may be not the target, need to search the abilityStack_
329 AbilityRecord *jsAbilityRecord = const_cast<AbilityRecord *>(abilityStack_.GetAbility(bundleName));
330 if (jsAbilityRecord != nullptr) {
331 jsAbilityRecord->SetTerminated(true);
332 // TerminateAbility top js
333 return SchedulerLifecycleInner(topRecord, STATE_UNINITIALIZED);
334 }
335 HILOG_INFO(HILOG_MODULE_AAFWK, "ForceStop cannot find exact Js ability");
336 #endif
337 }
338 return PARAM_CHECK_ERROR;
339 }
340
ForceStopBundleInner(uint16_t token)341 int32_t AbilityService::ForceStopBundleInner(uint16_t token)
342 {
343 // free js mem and delete the record
344 AbilityRecord *record = abilityList_.Get(token);
345 if (record == nullptr) {
346 return PARAM_NULL_ERROR;
347 }
348 auto jsAppHost = const_cast<JsAppHost *>(record->GetJsAppHost());
349 if (jsAppHost != nullptr) {
350 // free js mem
351 jsAppHost->ForceDestroy();
352 }
353 DeleteRecordInfo(token);
354 return ERR_OK;
355 }
356
PreCheckStartAbility(const char * bundleName,const char * path,const void * data,uint16_t dataLength)357 int32_t AbilityService::PreCheckStartAbility(
358 const char *bundleName, const char *path, const void *data, uint16_t dataLength)
359 {
360 if (path == nullptr) {
361 HILOG_ERROR(HILOG_MODULE_AAFWK, "PreCheckStartAbility path is null.");
362 return PARAM_NULL_ERROR;
363 }
364 auto curRecord = abilityList_.Get(bundleName);
365 if (curRecord != nullptr) {
366 if (curRecord->GetState() == SCHEDULE_ACTIVE) {
367 HILOG_ERROR(HILOG_MODULE_AAFWK, "PreCheckStartAbility current state active.");
368 } else if (curRecord->GetState() == SCHEDULE_BACKGROUND) {
369 SchedulerLifecycle(LAUNCHER_TOKEN, STATE_BACKGROUND);
370 }
371 return ERR_OK;
372 }
373 auto record = new AbilityRecord();
374 if (pendingToken_ != 0) {
375 record->SetToken(pendingToken_);
376 } else {
377 record->SetToken(GenerateToken());
378 }
379 record->SetAppName(bundleName);
380 record->SetAppPath(path);
381 record->SetAppData(data, dataLength);
382 record->SetState(SCHEDULE_STOP);
383 abilityList_.Add(record);
384 if (pendingToken_ == 0 && CreateAppTask(record) != ERR_OK) {
385 HILOG_ERROR(HILOG_MODULE_AAFWK, "CheckResponse CreateAppTask fail");
386 abilityList_.Erase(record->GetToken());
387 delete record;
388 return CREATE_APPTASK_ERROR;
389 }
390 return ERR_OK;
391 }
392
CheckResponse(const char * bundleName)393 bool AbilityService::CheckResponse(const char *bundleName)
394 {
395 StartCheckFunc callBackFunc = GetAbilityCallback();
396 if (callBackFunc == nullptr) {
397 HILOG_ERROR(HILOG_MODULE_AAFWK, "calling ability callback failed: null");
398 return true;
399 }
400 int32_t ret = (*callBackFunc)(bundleName);
401 if (ret != ERR_OK) {
402 HILOG_ERROR(HILOG_MODULE_AAFWK, "calling ability callback failed: check");
403 return false;
404 }
405 return true;
406 }
407
CreateAppTask(AbilityRecord * record)408 int32_t AbilityService::CreateAppTask(AbilityRecord *record)
409 {
410 if ((record == nullptr) || (record->GetAppName() == nullptr)) {
411 HILOG_ERROR(HILOG_MODULE_AAFWK, "CreateAppTask fail: null");
412 return PARAM_NULL_ERROR;
413 }
414
415 HILOG_INFO(HILOG_MODULE_AAFWK, "CreateAppTask.");
416 TSK_INIT_PARAM_S stTskInitParam = {0};
417 LOS_TaskLock();
418 stTskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)(JsAppHost::JsAppTaskHandler);
419 stTskInitParam.uwStackSize = TASK_STACK_SIZE;
420 stTskInitParam.usTaskPrio = OS_TASK_PRIORITY_LOWEST - APP_TASK_PRI;
421 stTskInitParam.pcName = const_cast<char *>("AppTask");
422 stTskInitParam.uwResved = 0;
423 auto jsAppHost = new JsAppHost();
424 stTskInitParam.uwArg = reinterpret_cast<UINT32>((uintptr_t)jsAppHost);
425 UINT32 appTaskId = 0;
426 UINT32 ret = LOS_TaskCreate(&appTaskId, &stTskInitParam);
427 if (ret != LOS_OK) {
428 HILOG_ERROR(HILOG_MODULE_AAFWK, "CreateAppTask fail: ret = %{public}d", ret);
429 APP_ERRCODE_EXTRA(EXCE_ACE_APP_START, EXCE_ACE_APP_START_CREATE_TSAK_FAILED);
430 delete jsAppHost;
431 LOS_TaskUnlock();
432 return CREATE_APPTASK_ERROR;
433 }
434 osMessageQueueId_t jsAppQueueId = osMessageQueueNew(QUEUE_LENGTH, sizeof(AbilityInnerMsg), nullptr);
435 jsAppHost->SetMessageQueueId(jsAppQueueId);
436 LOS_TaskUnlock();
437
438 record->SetTaskId(appTaskId);
439 record->SetMessageQueueId(jsAppQueueId);
440 record->SetJsAppHost(jsAppHost);
441
442 // LiteOS-M not support permissions checking right now, when permission checking is ready, we
443 // can remove the macro.
444 #ifndef __LITEOS_M__
445 LoadPermissions(record->GetAppName(), appTaskId);
446 #endif
447 record->SetState(SCHEDULE_INACTIVE);
448 abilityStack_.PushAbility(record);
449 APP_EVENT(MT_ACE_APP_START);
450 if (nativeAbility_ != nullptr) {
451 if (SchedulerLifecycle(LAUNCHER_TOKEN, STATE_BACKGROUND) != 0) {
452 APP_ERRCODE_EXTRA(EXCE_ACE_APP_START, EXCE_ACE_APP_START_LAUNCHER_EXIT_FAILED);
453 HILOG_INFO(HILOG_MODULE_AAFWK, "CreateAppTask Fail to hide launcher");
454 abilityStack_.PopAbility();
455 return SCHEDULER_LIFECYCLE_ERROR;
456 }
457 } else {
458 SchedulerLifecycle(record->GetToken(), STATE_ACTIVE);
459 }
460 return ERR_OK;
461 }
462
GenerateToken()463 uint16_t AbilityService::GenerateToken()
464 {
465 static uint16_t token = LAUNCHER_TOKEN;
466 if (token == UINT16_MAX - 1) {
467 token = LAUNCHER_TOKEN;
468 }
469 return ++token;
470 }
471
DeleteRecordInfo(uint16_t token)472 void AbilityService::DeleteRecordInfo(uint16_t token)
473 {
474 AbilityRecord *record = abilityList_.Get(token);
475 if (record == nullptr) {
476 return;
477 }
478 if (token != LAUNCHER_TOKEN) {
479 if (record->IsAttached()) {
480 UINT32 taskId = record->GetTaskId();
481 // LiteOS-M not support permissions checking right now, when permission checking is
482 // ready, we can remove the macro.
483 #ifndef __LITEOS_M__
484 UnLoadPermissions(taskId);
485 #endif
486 LOS_TaskDelete(taskId);
487 osMessageQueueId_t jsAppQueueId = record->GetMessageQueueId();
488 osMessageQueueDelete(jsAppQueueId);
489 auto jsAppHost = const_cast<JsAppHost *>(record->GetJsAppHost());
490 delete jsAppHost;
491 // free all JS native memory after exiting it
492 // CleanTaskMem(taskId)
493 }
494 // record app info event when stop app
495 RecordAbiityInfoEvt(record->GetAppName());
496 }
497 abilityStack_.Erase(record);
498 abilityList_.Erase(token);
499 delete record;
500 }
501
OnActiveDone(uint16_t token)502 void AbilityService::OnActiveDone(uint16_t token)
503 {
504 HILOG_INFO(HILOG_MODULE_AAFWK, "OnActiveDone [%{public}u]", token);
505 SetAbilityState(token, SCHEDULE_ACTIVE);
506 auto topRecord = const_cast<AbilityRecord *>(abilityStack_.GetTopAbility());
507 if (topRecord == nullptr) {
508 return;
509 }
510
511 // the launcher active
512 if (token == LAUNCHER_TOKEN) {
513 if (nativeAbility_== nullptr || nativeAbility_->GetState() != STATE_ACTIVE) {
514 HILOG_ERROR(HILOG_MODULE_AAFWK, "native ability is in wrong state : %{public}d", nativeAbility_->GetState());
515 return;
516 }
517 if (topRecord->GetToken() != LAUNCHER_TOKEN) {
518 int abilityState = STATE_UNINITIALIZED;
519 if (topRecord->GetState() == SCHEDULE_ACTIVE) {
520 HILOG_ERROR(HILOG_MODULE_AAFWK,
521 "js is in active state, native state is %{public}d", abilityState);
522 OnDestroyDone(topRecord->GetToken());
523 return;
524 }
525 if (topRecord->GetState() != SCHEDULE_BACKGROUND) {
526 APP_ERRCODE_EXTRA(EXCE_ACE_APP_START, EXCE_ACE_APP_START_LAUNCHER_EXIT_FAILED);
527 HILOG_ERROR(HILOG_MODULE_AAFWK,
528 "Active launcher js bg fail, native state is %{public}d", abilityState);
529 abilityStack_.PopAbility();
530 DeleteRecordInfo(topRecord->GetToken());
531 } else if (topRecord->IsTerminated()) {
532 (void) SchedulerLifecycleInner(topRecord, STATE_UNINITIALIZED);
533 }
534 }
535 return;
536 }
537 // the js app active
538 if (topRecord->GetToken() == token) {
539 APP_EVENT(MT_ACE_APP_ACTIVE);
540 }
541 }
542
OnBackgroundDone(uint16_t token)543 void AbilityService::OnBackgroundDone(uint16_t token)
544 {
545 HILOG_INFO(HILOG_MODULE_AAFWK, "OnBackgroundDone [%{public}u]", token);
546 SetAbilityState(token, SCHEDULE_BACKGROUND);
547 auto topRecord = const_cast<AbilityRecord *>(abilityStack_.GetTopAbility());
548 if (topRecord == nullptr) {
549 return;
550 }
551 // the js background
552 if (token != LAUNCHER_TOKEN) {
553 if (topRecord->GetToken() == token) {
554 APP_EVENT(MT_ACE_APP_BACKGROUND);
555 (void) SchedulerLifecycle(LAUNCHER_TOKEN, STATE_ACTIVE);
556 }
557 return;
558 }
559 // the launcher background
560 if (topRecord->GetToken() != LAUNCHER_TOKEN) {
561 (void) SchedulerLifecycleInner(topRecord, STATE_ACTIVE);
562 if (GetCleanAbilityDataFlag()) {
563 HILOG_INFO(HILOG_MODULE_AAFWK, "OnBackgroundDone clean launcher record data");
564 AbilityRecord *record = abilityList_.Get(token);
565 record->SetAppData(nullptr, 0);
566 SetCleanAbilityDataFlag(false);
567 }
568 return;
569 }
570 HILOG_WARN(HILOG_MODULE_AAFWK, "Js app exit, but has no js app.");
571 }
572
OnDestroyDone(uint16_t token)573 void AbilityService::OnDestroyDone(uint16_t token)
574 {
575 HILOG_INFO(HILOG_MODULE_AAFWK, "OnDestroyDone [%{public}u]", token);
576 // the launcher destroy
577 if (token == LAUNCHER_TOKEN) {
578 SetAbilityState(token, SCHEDULE_STOP);
579 return;
580 }
581 auto topRecord = abilityStack_.GetTopAbility();
582 if ((topRecord == nullptr) || (topRecord->GetToken() != token)) {
583 SetAbilityState(token, SCHEDULE_STOP);
584 DeleteRecordInfo(token);
585 return;
586 }
587 APP_EVENT(MT_ACE_APP_STOP);
588 abilityStack_.PopAbility();
589 DeleteRecordInfo(token);
590 SetAbilityState(token, SCHEDULE_STOP);
591
592 // no pending token
593 if (pendingToken_ == 0) {
594 (void) SchedulerLifecycle(LAUNCHER_TOKEN, STATE_ACTIVE);
595 return;
596 }
597
598 // start pending token
599 auto record = abilityList_.Get(pendingToken_);
600 if (CreateAppTask(record) != ERR_OK) {
601 abilityList_.Erase(pendingToken_);
602 delete record;
603 (void) SchedulerLifecycle(LAUNCHER_TOKEN, STATE_ACTIVE);
604 }
605 pendingToken_ = 0;
606 }
607
SchedulerLifecycle(uint64_t token,int32_t state)608 int32_t AbilityService::SchedulerLifecycle(uint64_t token, int32_t state)
609 {
610 AbilityRecord *record = abilityList_.Get(token);
611 if (record == nullptr) {
612 return PARAM_NULL_ERROR;
613 }
614 return SchedulerLifecycleInner(record, state);
615 }
616
SetAbilityState(uint64_t token,int32_t state)617 void AbilityService::SetAbilityState(uint64_t token, int32_t state)
618 {
619 AbilityRecord *record = abilityList_.Get(token);
620 if (record == nullptr) {
621 return;
622 }
623 record->SetState((AbilityState) state);
624 }
625
SchedulerLifecycleInner(const AbilityRecord * record,int32_t state)626 int32_t AbilityService::SchedulerLifecycleInner(const AbilityRecord *record, int32_t state)
627 {
628 if (record == nullptr) {
629 return PARAM_NULL_ERROR;
630 }
631 // dispatch js life cycle
632 if (record->GetToken() != LAUNCHER_TOKEN) {
633 (void) SendMsgToJsAbility(state, record);
634 return ERR_OK;
635 }
636 // dispatch native life cycle
637 if (nativeAbility_ == nullptr) {
638 return PARAM_NULL_ERROR;
639 }
640 // malloc want memory and release after use
641 Want *info = static_cast<Want *>(AdapterMalloc(sizeof(Want)));
642 if (info == nullptr) {
643 return MEMORY_MALLOC_ERROR;
644 }
645 info->element = nullptr;
646 info->data = nullptr;
647 info->dataLength = 0;
648
649 ElementName elementName = {};
650 SetElementBundleName(&elementName, LAUNCHER_BUNDLE_NAME);
651 SetWantElement(info, elementName);
652 ClearElement(&elementName);
653 SetWantData(info, record->GetAppData(), record->GetDataLength());
654 SchedulerAbilityLifecycle(nativeAbility_, *info, state);
655 ClearWant(info);
656 AdapterFree(info);
657 return ERR_OK;
658 }
659
SchedulerAbilityLifecycle(SliteAbility * ability,const Want & want,int32_t state)660 void AbilityService::SchedulerAbilityLifecycle(SliteAbility *ability, const Want &want, int32_t state)
661 {
662 if (ability == nullptr) {
663 return;
664 }
665 switch (state) {
666 case STATE_ACTIVE: {
667 ability->OnActive(want);
668 break;
669 }
670 case STATE_BACKGROUND: {
671 ability->OnBackground();
672 break;
673 }
674 default: {
675 break;
676 }
677 }
678 return;
679 }
680
SchedulerLifecycleDone(uint64_t token,int32_t state)681 int32_t AbilityService::SchedulerLifecycleDone(uint64_t token, int32_t state)
682 {
683 switch (state) {
684 case STATE_ACTIVE: {
685 OnActiveDone(token);
686 break;
687 }
688 case STATE_BACKGROUND: {
689 OnBackgroundDone(token);
690 break;
691 }
692 case STATE_UNINITIALIZED: {
693 OnDestroyDone(token);
694 break;
695 }
696 default: {
697 break;
698 }
699 }
700 return ERR_OK;
701 }
702
SendMsgToJsAbility(int32_t state,const AbilityRecord * record)703 bool AbilityService::SendMsgToJsAbility(int32_t state, const AbilityRecord *record)
704 {
705 if (record == nullptr) {
706 return false;
707 }
708
709 AbilityInnerMsg innerMsg;
710 if (state == STATE_ACTIVE) {
711 innerMsg.msgId = ACTIVE;
712 } else if (state == STATE_BACKGROUND) {
713 innerMsg.msgId = BACKGROUND;
714 } else if (state == STATE_UNINITIALIZED) {
715 innerMsg.msgId = DESTROY;
716 } else {
717 innerMsg.msgId = (AbilityMsgId) state;
718 }
719 innerMsg.bundleName = record->GetAppName();
720 innerMsg.token = record->GetToken();
721 innerMsg.path = record->GetAppPath();
722 innerMsg.data = const_cast<void *>(record->GetAppData());
723 innerMsg.dataLength = record->GetDataLength();
724 osMessageQueueId_t appQueueId = record->GetMessageQueueId();
725 osStatus_t ret = osMessageQueuePut(appQueueId, static_cast<void *>(&innerMsg), 0, 0);
726 return ret == osOK;
727 }
728
GetTopAbility()729 ElementName *AbilityService::GetTopAbility()
730 {
731 auto topRecord = const_cast<AbilityRecord *>(abilityStack_.GetTopAbility());
732 AbilityRecord *launcherRecord = abilityList_.Get(LAUNCHER_TOKEN);
733 if (topRecord == nullptr || launcherRecord == nullptr) {
734 return nullptr;
735 }
736 ElementName *element = reinterpret_cast<ElementName *>(AdapterMalloc(sizeof(ElementName)));
737 if (element == nullptr || memset_s(element, sizeof(ElementName), 0, sizeof(ElementName)) != EOK) {
738 AdapterFree(element);
739 return nullptr;
740 }
741 if (topRecord->GetToken() == LAUNCHER_TOKEN || launcherRecord->GetState() == SCHEDULE_ACTIVE) {
742 SetElementBundleName(element, LAUNCHER_BUNDLE_NAME);
743 return element;
744 }
745
746 // case js active or background when launcher not active
747 if (topRecord->GetState() == SCHEDULE_ACTIVE || topRecord->GetState() == SCHEDULE_BACKGROUND) {
748 SetElementBundleName(element, topRecord->GetAppName());
749 }
750 return element;
751 }
752
setNativeAbility(const SliteAbility * ability)753 void AbilityService::setNativeAbility(const SliteAbility *ability)
754 {
755 nativeAbility_ = const_cast<SliteAbility *>(ability);
756 }
757 } // namespace OHOS
758
759 extern "C" {
InstallNativeAbility(const AbilityInfo * abilityInfo,const OHOS::SliteAbility * ability)760 int InstallNativeAbility(const AbilityInfo *abilityInfo, const OHOS::SliteAbility *ability)
761 {
762 OHOS::AbilityService::GetInstance().setNativeAbility(ability);
763 return ERR_OK;
764 }
765
GetTopAbility()766 ElementName *GetTopAbility()
767 {
768 return OHOS::AbilityService::GetInstance().GetTopAbility();
769 }
770 }
771