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