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