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 <cstring>
17 #include "abilityms_log.h"
18 #include "ability_errors.h"
19 #include "ability_list.h"
20 #include "ability_lock_guard.h"
21 #include "ability_record.h"
22 #include "ability_record_observer_manager.h"
23
24 namespace OHOS {
25 namespace AbilitySlite {
AbilityList()26 AbilityList::AbilityList()
27 {
28 abilityListMutex_ = osMutexNew(reinterpret_cast<osMutexAttr_t *>(NULL));
29 }
30
~AbilityList()31 AbilityList::~AbilityList()
32 {
33 osMutexDelete(abilityListMutex_);
34 }
35
Add(AbilityRecord * abilityRecord)36 void AbilityList::Add(AbilityRecord *abilityRecord)
37 {
38 AbilityLockGuard locker(abilityListMutex_);
39 if (abilityRecord == nullptr) {
40 return;
41 }
42 if (abilityList_.Size() >= ABILITY_LIST_CAPACITY) {
43 PopBottomAbility();
44 }
45
46 if (Get(abilityRecord->token) == nullptr) {
47 abilityList_.PushFront(abilityRecord);
48 }
49 }
50
Get(uint16_t token) const51 AbilityRecord *AbilityList::Get(uint16_t token) const
52 {
53 AbilityLockGuard locker(abilityListMutex_);
54 for (auto node = abilityList_.Begin(); node != abilityList_.End(); node = node->next_) {
55 AbilityRecord *record = node->value_;
56 if (record == nullptr) {
57 continue;
58 }
59 if (record->token == token) {
60 return record;
61 }
62 }
63
64 return nullptr;
65 }
66
Get(const char * bundleName) const67 AbilityRecord *AbilityList::Get(const char *bundleName) const
68 {
69 if (bundleName == nullptr) {
70 return nullptr;
71 }
72
73 AbilityLockGuard locker(abilityListMutex_);
74 for (auto node = abilityList_.Begin(); node != abilityList_.End(); node = node->next_) {
75 AbilityRecord *record = node->value_;
76 if (record == nullptr || record->appName == nullptr) {
77 continue;
78 }
79 if (strcmp(bundleName, record->appName) == 0) {
80 return record;
81 }
82 }
83 return nullptr;
84 }
85
GetByTaskId(uint32_t taskId) const86 AbilityRecord *AbilityList::GetByTaskId(uint32_t taskId) const
87 {
88 AbilityLockGuard locker(abilityListMutex_);
89 for (auto node = abilityList_.Begin(); node != abilityList_.End(); node = node->next_) {
90 AbilityRecord *record = node->value_;
91 if (record == nullptr) {
92 continue;
93 }
94 if (record->taskId == taskId) {
95 return record;
96 }
97 }
98 return nullptr;
99 }
100
Erase(uint16_t token)101 void AbilityList::Erase(uint16_t token)
102 {
103 AbilityLockGuard locker(abilityListMutex_);
104 for (auto node = abilityList_.Begin(); node != abilityList_.End(); node = node->next_) {
105 AbilityRecord *record = node->value_;
106 if (record == nullptr) {
107 continue;
108 }
109 if (record->token == token) {
110 abilityList_.Remove(node);
111 return;
112 }
113 }
114 }
115
GetAbilityList(uint32_t mission,List<uint32_t> & result)116 void AbilityList::GetAbilityList(uint32_t mission, List<uint32_t> &result)
117 {
118 AbilityLockGuard locker(abilityListMutex_);
119
120 for (auto node = abilityList_.Begin(); node != abilityList_.End(); node = node->next_) {
121 AbilityRecord *record = node->value_;
122 if ((record != nullptr) && (record->mission == mission)) {
123 result.PushFront(record->token);
124 }
125 }
126 }
127
Size() const128 uint32_t AbilityList::Size() const
129 {
130 AbilityLockGuard locker(abilityListMutex_);
131 return abilityList_.Size();
132 }
133
MoveToTop(uint16_t token)134 bool AbilityList::MoveToTop(uint16_t token)
135 {
136 AbilityLockGuard locker(abilityListMutex_);
137 AbilityRecord *abilityRecord = Get(token);
138 if (abilityRecord == nullptr) {
139 return false;
140 }
141 Erase(token);
142 Add(abilityRecord);
143 return true;
144 }
145
PopAbility()146 void AbilityList::PopAbility()
147 {
148 AbilityLockGuard locker(abilityListMutex_);
149 abilityList_.PopFront();
150 }
151
GetTopAbility() const152 AbilityRecord *AbilityList::GetTopAbility() const
153 {
154 AbilityLockGuard locker(abilityListMutex_);
155 if (abilityList_.Size() != 0) {
156 return abilityList_.Front();
157 }
158 return nullptr;
159 }
160
GetMissionInfos(uint32_t maxNum) const161 MissionInfoList *AbilityList::GetMissionInfos(uint32_t maxNum) const
162 {
163 AbilityLockGuard lock(abilityListMutex_);
164 MissionInfoList *missionInfoList = new MissionInfoList;
165 if (missionInfoList == nullptr) {
166 HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to new MissionInfoList.");
167 return nullptr;
168 }
169 missionInfoList->length = abilityList_.Size();
170 if (maxNum != 0) {
171 missionInfoList->length = (missionInfoList->length > maxNum) ? maxNum : missionInfoList->length;
172 }
173 missionInfoList->missionInfos = new MissionInfo[missionInfoList->length];
174 if (missionInfoList->missionInfos == nullptr) {
175 HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to new missionInfos.");
176 delete missionInfoList;
177 return nullptr;
178 }
179 uint32_t i = 0;
180 for (auto it = abilityList_.Begin(); i < missionInfoList->length; it = it->next_) {
181 missionInfoList->missionInfos[i++].SetAppName(it->value_->appName);
182 }
183 return missionInfoList;
184 }
185
PopBottomAbility()186 void AbilityList::PopBottomAbility()
187 {
188 AbilityLockGuard locker(abilityListMutex_);
189 AbilityRecord *lastRecord = abilityList_.Back();
190 if (lastRecord == nullptr) {
191 abilityList_.PopBack();
192 return;
193 }
194 if (!IsPermanentAbility(*lastRecord)) {
195 abilityList_.PopBack();
196 delete lastRecord;
197 return;
198 }
199 // last record is home
200 abilityList_.PopBack(); // pop home
201 AbilityRecord *secondLastRecord = abilityList_.Back();
202 abilityList_.PopBack(); // pop secondLastRecord
203 delete secondLastRecord;
204 abilityList_.PushBack(lastRecord); // push back home
205 }
206
PopAllAbility(const char * excludedBundleName)207 int32_t AbilityList::PopAllAbility(const char *excludedBundleName)
208 {
209 AbilityLockGuard locker(abilityListMutex_);
210 OHOS::List<AbilityRecord *> reservedRecordList {};
211 AbilityRecord *topRecord = abilityList_.Front();
212 if (topRecord == nullptr) {
213 return PARAM_NULL_ERROR;
214 }
215 abilityList_.PopFront();
216 reservedRecordList.PushFront(topRecord);
217
218 while (abilityList_.Size() > 0) {
219 AbilityRecord *record = abilityList_.Front();
220 abilityList_.PopFront();
221 if (record == nullptr) {
222 continue;
223 }
224 if (AbilityList::IsPermanentAbility(*record)) {
225 reservedRecordList.PushFront(record);
226 continue;
227 }
228 if (excludedBundleName != nullptr && strcmp(record->appName, excludedBundleName) == 0) {
229 reservedRecordList.PushFront(record);
230 continue;
231 }
232 AbilityRecordObserverManager::GetInstance().NotifyAbilityRecordCleanup(record->appName);
233 delete record;
234 }
235 while (reservedRecordList.Size() > 0) {
236 AbilityRecord *record = reservedRecordList.Front();
237 reservedRecordList.PopFront();
238 if (record == nullptr) {
239 continue;
240 }
241 abilityList_.PushFront(record);
242 }
243 return ERR_OK;
244 }
245
IsPermanentAbility(const AbilityRecord & abilityRecord)246 bool AbilityList::IsPermanentAbility(const AbilityRecord &abilityRecord)
247 {
248 if (abilityRecord.appName == nullptr) {
249 return false;
250 }
251 if (abilityRecord.token == LAUNCHER_TOKEN) {
252 return true;
253 }
254 if (strcmp(abilityRecord.appName, MAIN_BUNDLE_NAME) == 0) {
255 return true;
256 }
257 return false;
258 }
259 } // namespace AbilitySlite
260 } // namespace OHOS
261