• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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