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 "js_ability_thread.h"
17 
18 #include "abilityms_log.h"
19 #include "ability_errors.h"
20 #include "ability_inner_message.h"
21 #include "adapter.h"
22 #include "js_ability.h"
23 #include "js_async_work.h"
24 #include "los_task.h"
25 #include "slite_ability_loader.h"
26 
27 namespace OHOS {
28 namespace AbilitySlite {
29 constexpr uint16_t APP_TASK_PRI = 25;
30 constexpr uint32_t QUEUE_LENGTH = 32;
31 static char g_jsAppTask[] = "AppTask";
32 
33 JsAbilityThread::JsAbilityThread() = default;
34 
~JsAbilityThread()35 JsAbilityThread::~JsAbilityThread()
36 {
37     delete ability_;
38     ability_ = nullptr;
39     if (messageQueueId_ != nullptr) {
40         osMessageQueueDelete(messageQueueId_);
41         messageQueueId_ = nullptr;
42     }
43 }
44 
InitAbilityThread(const AbilityRecord * abilityRecord)45 int32_t JsAbilityThread::InitAbilityThread(const AbilityRecord *abilityRecord)
46 {
47     if (abilityRecord == nullptr) {
48         HILOG_ERROR(HILOG_MODULE_AAFWK, "JsAbilityThread init fail, abilityRecord is null");
49         return PARAM_NULL_ERROR;
50     }
51     if (abilityRecord->appName == nullptr) {
52         HILOG_ERROR(HILOG_MODULE_AAFWK, "JsAbilityThread init fail, appName is null");
53         return PARAM_NULL_ERROR;
54     }
55     if (state_ != AbilityThreadState::ABILITY_THREAD_UNINITIALIZED) {
56         HILOG_ERROR(HILOG_MODULE_AAFWK, "JsAbilityThread init fail, the AbilityThread is already inited");
57         return PARAM_CHECK_ERROR;
58     }
59 
60     messageQueueId_ = osMessageQueueNew(QUEUE_LENGTH, sizeof(SliteAbilityInnerMsg), nullptr);
61     if (messageQueueId_ == nullptr) {
62         HILOG_ERROR(HILOG_MODULE_AAFWK, "JsAbilityThread init fail: messageQueueId is null");
63         return MEMORY_MALLOC_ERROR;
64     }
65 
66     TSK_INIT_PARAM_S stTskInitParam = { nullptr };
67     LOS_TaskLock();
68     stTskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC) (JsAbilityThread::AppTaskHandler);
69     stTskInitParam.uwStackSize = TASK_STACK_SIZE;
70     stTskInitParam.usTaskPrio = OS_TASK_PRIORITY_LOWEST - APP_TASK_PRI;
71     stTskInitParam.pcName = g_jsAppTask;
72     stTskInitParam.uwResved = 0;
73     stTskInitParam.uwArg = reinterpret_cast<uintptr_t>(messageQueueId_);
74     uint32_t ret = LOS_TaskCreate(&appTaskId_, &stTskInitParam);
75     if (ret != LOS_OK) {
76         HILOG_ERROR(HILOG_MODULE_AAFWK, "JsAbilityThread init fail: LOS_TaskCreate ret %{public}d", ret);
77         osMessageQueueDelete(messageQueueId_);
78         LOS_TaskUnlock();
79         return CREATE_APPTASK_ERROR;
80     }
81     state_ = AbilityThreadState::ABILITY_THREAD_INITIALIZED;
82     ability_ = SliteAbilityLoader::GetInstance().CreateAbility(SliteAbilityType::JS_ABILITY, abilityRecord->appName);
83     if (ability_ == nullptr) {
84         HILOG_INFO(HILOG_MODULE_AAFWK, "JsAbility create fail");
85         return MEMORY_MALLOC_ERROR;
86     }
87     ability_->SetToken(abilityRecord->token);
88     ACELite::JsAsyncWork::SetAppQueueHandler(messageQueueId_);
89     LOS_TaskUnlock();
90     HILOG_INFO(HILOG_MODULE_AAFWK, "JsAbilityThread init done");
91     return ERR_OK;
92 }
93 
ReleaseAbilityThread()94 int32_t JsAbilityThread::ReleaseAbilityThread()
95 {
96     ACELite::JsAsyncWork::SetAppQueueHandler(nullptr);
97     if (state_ != AbilityThreadState::ABILITY_THREAD_INITIALIZED) {
98         HILOG_ERROR(HILOG_MODULE_AAFWK, "JsAbilityThread release fail, the AbilityThread is not inited");
99         return PARAM_CHECK_ERROR;
100     }
101     state_ = AbilityThreadState::ABILITY_THREAD_RELEASED;
102     LOS_TaskDelete(appTaskId_);
103     appTaskId_ = 0;
104     osMessageQueueDelete(messageQueueId_);
105     messageQueueId_ = nullptr;
106     return ERR_OK;
107 }
108 
GetMessageQueueId() const109 osMessageQueueId_t JsAbilityThread::GetMessageQueueId() const
110 {
111     return messageQueueId_;
112 }
113 
GetAppTaskId() const114 UINT32 JsAbilityThread::GetAppTaskId() const
115 {
116     return appTaskId_;
117 }
118 
AppTaskHandler(UINT32 uwArg)119 void JsAbilityThread::AppTaskHandler(UINT32 uwArg)
120 {
121     auto messageQueueId = reinterpret_cast<osMessageQueueId_t>(uwArg);
122     if (messageQueueId == nullptr) {
123         return;
124     }
125     AbilityThread *defaultAbilityThread = nullptr;
126 
127     for (;;) {
128         SliteAbilityInnerMsg innerMsg;
129         uint8_t prio = 0;
130         osStatus_t ret = osMessageQueueGet(messageQueueId, &innerMsg, &prio, osWaitForever);
131         if (ret != osOK) {
132             return;
133         }
134         AbilityThread *abilityThread = innerMsg.abilityThread;
135         if (abilityThread == nullptr) {
136             if (defaultAbilityThread == nullptr) {
137                 continue;
138             }
139             abilityThread = defaultAbilityThread;
140         }
141         LP_TaskBegin();
142         switch (innerMsg.msgId) {
143             case SliteAbilityMsgId::CREATE:
144                 defaultAbilityThread = abilityThread;
145                 abilityThread->HandleCreate(innerMsg.want);
146                 abilityThread->HandleRestore(innerMsg.abilitySavedData);
147                 ClearWant(innerMsg.want);
148                 AdapterFree(innerMsg.want);
149                 innerMsg.want = nullptr;
150                 break;
151             case SliteAbilityMsgId::FOREGROUND:
152                 abilityThread->HandleForeground(innerMsg.want);
153                 ClearWant(innerMsg.want);
154                 AdapterFree(innerMsg.want);
155                 innerMsg.want = nullptr;
156                 break;
157             case SliteAbilityMsgId::BACKGROUND:
158                 abilityThread->HandleBackground();
159                 break;
160             case SliteAbilityMsgId::DESTROY:
161                 abilityThread->HandleSave(innerMsg.abilitySavedData);
162                 abilityThread->HandleDestroy();
163                 LP_TaskEnd();
164                 return; // here exit the loop, and abort all messages afterwards
165             default:
166                 if (abilityThread->ability_ != nullptr) {
167                     abilityThread->ability_->HandleExtraMessage(innerMsg);
168                 }
169                 break;
170         }
171         LP_TaskEnd();
172     }
173 }
174 } // namespace AbilitySlite
175 } // namespace OHOS
176