1 /*
2  * Copyright (c) 2024 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_cache_manager.h"
17 
18 #include "hilog_tag_wrapper.h"
19 
20 namespace OHOS {
21 namespace AAFwk {
22 const std::string FRS_APP_INDEX = "ohos.extra.param.key.frs_index";
23 const std::string FRS_BUNDLE_NAME = "com.ohos.formrenderservice";
24 
AbilityCacheManager()25 AbilityCacheManager::AbilityCacheManager() {}
26 
~AbilityCacheManager()27 AbilityCacheManager::~AbilityCacheManager() {}
28 
GetInstance()29 AbilityCacheManager &AbilityCacheManager::GetInstance()
30 {
31     static AbilityCacheManager abilityRecMgr;
32     return abilityRecMgr;
33 }
34 
Init(uint32_t devCapacity,uint32_t procCapacity)35 void AbilityCacheManager::Init(uint32_t devCapacity, uint32_t procCapacity)
36 {
37     devLruCapacity_ = devCapacity;
38     procLruCapacity_ = procCapacity;
39 }
40 
RemoveAbilityRecInDevList(std::shared_ptr<AbilityRecord> abilityRecord)41 void AbilityCacheManager::RemoveAbilityRecInDevList(std::shared_ptr<AbilityRecord> abilityRecord)
42 {
43     auto it = devRecLru_.begin();
44     uint32_t accessTokenId = abilityRecord->GetApplicationInfo().accessTokenId;
45     while (it != devRecLru_.end()) {
46         if ((*it)->GetRecordId() == abilityRecord->GetRecordId()) {
47             devRecLru_.erase(it);
48             devLruCnt_--;
49             return;
50         } else {
51             it++;
52         }
53     }
54 }
55 
RemoveAbilityRecInProcList(std::shared_ptr<AbilityRecord> abilityRecord)56 void AbilityCacheManager::RemoveAbilityRecInProcList(std::shared_ptr<AbilityRecord> abilityRecord)
57 {
58     uint32_t accessTokenId = abilityRecord->GetApplicationInfo().accessTokenId;
59     auto findProcInfo = procLruMap_.find(accessTokenId);
60     if (findProcInfo == procLruMap_.end()) {
61         TAG_LOGE(AAFwkTag::ABILITYMGR, "Can't found the abilityRecord in process list for remove.");
62         return;
63     }
64     auto it = findProcInfo->second.recList.begin();
65 
66     while (it != findProcInfo->second.recList.end()) {
67         if ((*it)->GetRecordId() == abilityRecord->GetRecordId()) {
68             findProcInfo->second.recList.erase(it);
69             findProcInfo->second.cnt--;
70             if (findProcInfo->second.cnt == 0) {
71                 procLruMap_.erase(findProcInfo);
72             }
73             return;
74         } else {
75             it++;
76         }
77     }
78 }
79 
AddToProcLru(std::shared_ptr<AbilityRecord> abilityRecord)80 std::shared_ptr<AbilityRecord> AbilityCacheManager::AddToProcLru(std::shared_ptr<AbilityRecord> abilityRecord)
81 {
82     auto findProcInfo = procLruMap_.find(abilityRecord->GetApplicationInfo().accessTokenId);
83     if (findProcInfo == procLruMap_.end()) {
84         std::list<std::shared_ptr<AbilityRecord>> recList;
85         ProcRecordsInfo procRecInfo = {recList, 1};
86         procRecInfo.recList.push_back(abilityRecord);
87         procLruMap_[abilityRecord->GetApplicationInfo().accessTokenId] = procRecInfo;
88         return nullptr;
89     }
90     if (findProcInfo->second.cnt == procLruCapacity_) {
91         RemoveAbilityRecInDevList(findProcInfo->second.recList.front());
92         std::shared_ptr<AbilityRecord> rec = findProcInfo->second.recList.front();
93         findProcInfo->second.recList.pop_front();
94         findProcInfo->second.recList.push_back(abilityRecord);
95         return rec;
96     }
97     findProcInfo->second.cnt++;
98     findProcInfo->second.recList.push_back(abilityRecord);
99     return nullptr;
100 }
101 
AddToDevLru(std::shared_ptr<AbilityRecord> abilityRecord,std::shared_ptr<AbilityRecord> rec)102 std::shared_ptr<AbilityRecord> AbilityCacheManager::AddToDevLru(std::shared_ptr<AbilityRecord> abilityRecord,
103     std::shared_ptr<AbilityRecord> rec)
104 {
105     if (rec != nullptr) {
106         devRecLru_.push_back(abilityRecord);
107         devLruCnt_++;
108         return rec;
109     }
110     if (devLruCnt_ == devLruCapacity_) {
111         rec = devRecLru_.front();
112         RemoveAbilityRecInProcList(rec);
113         devRecLru_.pop_front();
114         devLruCnt_--;
115     }
116     devRecLru_.push_back(abilityRecord);
117     devLruCnt_++;
118     return rec;
119 }
120 
Put(std::shared_ptr<AbilityRecord> abilityRecord)121 std::shared_ptr<AbilityRecord> AbilityCacheManager::Put(std::shared_ptr<AbilityRecord> abilityRecord)
122 {
123     if (abilityRecord == nullptr) {
124         TAG_LOGE(AAFwkTag::ABILITYMGR, "The param abilityRecord is nullptr for Put operation.");
125         return nullptr;
126     }
127     TAG_LOGD(AAFwkTag::ABILITYMGR, "Put the ability to lru, service:%{public}s, extension type %{public}d",
128         abilityRecord->GetURI().c_str(), abilityRecord->GetAbilityInfo().extensionAbilityType);
129     std::lock_guard<std::mutex> lock(mutex_);
130     std::shared_ptr<AbilityRecord> rec = AddToProcLru(abilityRecord);
131     return AddToDevLru(abilityRecord, rec);
132 }
133 
Remove(std::shared_ptr<AbilityRecord> abilityRecord)134 void AbilityCacheManager::Remove(std::shared_ptr<AbilityRecord> abilityRecord)
135 {
136     if (abilityRecord == nullptr) {
137         TAG_LOGE(AAFwkTag::ABILITYMGR, "The param abilityRecord is nullptr for Remove operation.");
138         return;
139     }
140     TAG_LOGD(AAFwkTag::ABILITYMGR, "Remove the ability from lru, service:%{public}s, extension type %{public}d",
141         abilityRecord->GetURI().c_str(), abilityRecord->GetAbilityInfo().extensionAbilityType);
142     std::lock_guard<std::mutex> lock(mutex_);
143     RemoveAbilityRecInProcList(abilityRecord);
144     RemoveAbilityRecInDevList(abilityRecord);
145 }
146 
IsRecInfoSame(const AbilityRequest & abilityRequest,std::shared_ptr<AbilityRecord> abilityRecord)147 bool AbilityCacheManager::IsRecInfoSame(const AbilityRequest& abilityRequest,
148     std::shared_ptr<AbilityRecord> abilityRecord)
149 {
150     return abilityRequest.abilityInfo.moduleName == abilityRecord->GetAbilityInfo().moduleName &&
151         abilityRequest.want.GetElement().GetAbilityName() == abilityRecord->GetWant().GetElement().GetAbilityName();
152 }
153 
GetAbilityRecInProcList(const AbilityRequest & abilityRequest)154 std::shared_ptr<AbilityRecord> AbilityCacheManager::GetAbilityRecInProcList(const AbilityRequest &abilityRequest)
155 {
156     auto findProcInfo = procLruMap_.find(abilityRequest.appInfo.accessTokenId);
157     if (findProcInfo == procLruMap_.end()) {
158         TAG_LOGE(AAFwkTag::ABILITYMGR, "Can't found the bundleName in process list for get.");
159         return nullptr;
160     }
161     ProcRecordsInfo &procRecordsInfo = findProcInfo->second;
162     auto recIter = procRecordsInfo.recList.begin();
163     while (recIter != procRecordsInfo.recList.end()) {
164         if (IsRecInfoSame(abilityRequest, *recIter)) {
165             std::shared_ptr<AbilityRecord> abilityRecord = *recIter;
166             procRecordsInfo.recList.erase(recIter);
167             procRecordsInfo.cnt--;
168             return abilityRecord;
169         }
170         recIter++;
171     }
172     TAG_LOGD(AAFwkTag::ABILITYMGR, "Can't found the abilityRecord in process list for get.");
173     return nullptr;
174 }
175 
Get(const AbilityRequest & abilityRequest)176 std::shared_ptr<AbilityRecord> AbilityCacheManager::Get(const AbilityRequest& abilityRequest)
177 {
178     TAG_LOGD(AAFwkTag::ABILITYMGR, "Get the ability from lru, service:%{public}s, extension type %{public}d",
179         abilityRequest.abilityInfo.uri.c_str(), abilityRequest.abilityInfo.extensionAbilityType);
180     std::lock_guard<std::mutex> lock(mutex_);
181     std::shared_ptr<AbilityRecord> abilityRecord = GetAbilityRecInProcList(abilityRequest);
182     if (abilityRecord == nullptr) {
183         TAG_LOGD(AAFwkTag::ABILITYMGR, "Can't found the abilityRecord for get.");
184         return nullptr;
185     }
186     RemoveAbilityRecInDevList(abilityRecord);
187     return abilityRecord;
188 }
189 
FindRecordByToken(const sptr<IRemoteObject> & token)190 std::shared_ptr<AbilityRecord> AbilityCacheManager::FindRecordByToken(const sptr<IRemoteObject> &token)
191 {
192     if (token == nullptr) {
193         TAG_LOGE(AAFwkTag::ABILITYMGR, "The param token is nullptr for FindRecordByToken operation.");
194         return nullptr;
195     }
196     std::lock_guard<std::mutex> lock(mutex_);
197     auto it = devRecLru_.begin();
198     while (it != devRecLru_.end()) {
199         sptr<IRemoteObject> srcToken = (*it)->GetToken();
200         if (srcToken == token) {
201             std::shared_ptr<AbilityRecord> &abilityRecord = *it;
202             TAG_LOGD(AAFwkTag::ABILITYMGR,
203                 "Find the ability by token from lru, service:%{public}s, extension type %{public}d",
204                 abilityRecord->GetURI().c_str(), abilityRecord->GetAbilityInfo().extensionAbilityType);
205             return abilityRecord;
206         } else {
207             it++;
208         }
209     }
210     return nullptr;
211 }
212 
GetAbilityList()213 std::list<std::shared_ptr<AbilityRecord>> AbilityCacheManager::GetAbilityList()
214 {
215     std::lock_guard<std::mutex> lock(mutex_);
216     return devRecLru_;
217 }
218 
FindRecordBySessionId(const std::string & assertSessionId)219 std::shared_ptr<AbilityRecord> AbilityCacheManager::FindRecordBySessionId(const std::string &assertSessionId)
220 {
221     std::lock_guard<std::mutex> lock(mutex_);
222     auto it = devRecLru_.begin();
223     while (it != devRecLru_.end()) {
224         auto assertSessionStr = (*it)->GetWant().GetStringParam(Want::PARAM_ASSERT_FAULT_SESSION_ID);
225         if (assertSessionStr == assertSessionId) {
226             std::shared_ptr<AbilityRecord> &abilityRecord = *it;
227             TAG_LOGD(AAFwkTag::ABILITYMGR,
228                 "Find the ability by sessionId from lru, service:%{public}s, extension type %{public}d",
229                 abilityRecord->GetURI().c_str(), abilityRecord->GetAbilityInfo().extensionAbilityType);
230             return abilityRecord;
231         } else {
232             it++;
233         }
234     }
235     return nullptr;
236 }
237 
FindRecordByServiceKey(const std::string & serviceKey)238 std::shared_ptr<AbilityRecord> AbilityCacheManager::FindRecordByServiceKey(const std::string &serviceKey)
239 {
240     std::lock_guard<std::mutex> lock(mutex_);
241     auto it = devRecLru_.begin();
242     while (it != devRecLru_.end()) {
243         std::string curServiceKey = (*it)->GetURI();
244         if (FRS_BUNDLE_NAME == (*it)->GetAbilityInfo().bundleName) {
245             curServiceKey = curServiceKey + std::to_string((*it)->GetWant().GetIntParam(FRS_APP_INDEX, 0));
246         }
247         if (curServiceKey.compare(serviceKey) == 0) {
248             std::shared_ptr<AbilityRecord> &abilityRecord = *it;
249             TAG_LOGD(AAFwkTag::ABILITYMGR,
250                 "Find the ability by serviceKey from lru, service:%{public}s, extension type %{public}d",
251                 abilityRecord->GetURI().c_str(), abilityRecord->GetAbilityInfo().extensionAbilityType);
252             return abilityRecord;
253         } else {
254             it++;
255         }
256     }
257     return nullptr;
258 }
259 
RemoveLauncherDeathRecipient()260 void AbilityCacheManager::RemoveLauncherDeathRecipient()
261 {
262     std::lock_guard<std::mutex> lock(mutex_);
263     auto it = devRecLru_.begin();
264     while (it != devRecLru_.end()) {
265         auto targetExtension = *it;
266         if (targetExtension != nullptr && targetExtension->GetAbilityInfo().type == AbilityType::EXTENSION &&
267             ((targetExtension->GetAbilityInfo().name == AbilityConfig::LAUNCHER_ABILITY_NAME &&
268             targetExtension->GetAbilityInfo().bundleName == AbilityConfig::LAUNCHER_BUNDLE_NAME) ||
269             targetExtension->IsSceneBoard())) {
270             targetExtension->RemoveAbilityDeathRecipient();
271             return;
272         }
273         it++;
274     }
275 }
276 
SignRestartAppFlag(int32_t uid)277 void AbilityCacheManager::SignRestartAppFlag(int32_t uid)
278 {
279     std::lock_guard<std::mutex> lock(mutex_);
280     auto it = devRecLru_.begin();
281     while (it != devRecLru_.end()) {
282         auto abilityRecord = *it;
283         if (abilityRecord != nullptr && abilityRecord->GetUid() == uid) {
284             abilityRecord->SetRestartAppFlag(true);
285         }
286         it++;
287     }
288 }
289 
DeleteInvalidServiceRecord(const std::string & bundleName)290 void AbilityCacheManager::DeleteInvalidServiceRecord(const std::string &bundleName)
291 {
292     std::lock_guard<std::mutex> lock(mutex_);
293     auto it = devRecLru_.begin();
294     while (it != devRecLru_.end()) {
295         auto abilityRecord = *it;
296         if (abilityRecord != nullptr && abilityRecord->GetApplicationInfo().bundleName == bundleName) {
297             RemoveAbilityRecInProcList(abilityRecord);
298             RemoveAbilityRecInDevList(abilityRecord);
299         }
300         it++;
301     }
302 }
303 }  // namespace AAFwk
304 } // namespace OHOS