1a3e0fd82Sopenharmony_ci/*
2a3e0fd82Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3a3e0fd82Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4a3e0fd82Sopenharmony_ci * you may not use this file except in compliance with the License.
5a3e0fd82Sopenharmony_ci * You may obtain a copy of the License at
6a3e0fd82Sopenharmony_ci *
7a3e0fd82Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8a3e0fd82Sopenharmony_ci *
9a3e0fd82Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10a3e0fd82Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11a3e0fd82Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12a3e0fd82Sopenharmony_ci * See the License for the specific language governing permissions and
13a3e0fd82Sopenharmony_ci * limitations under the License.
14a3e0fd82Sopenharmony_ci */
15a3e0fd82Sopenharmony_ci
16a3e0fd82Sopenharmony_ci#include "imgdecode/cache_manager.h"
17a3e0fd82Sopenharmony_ci#include "gfx_utils/graphic_log.h"
18a3e0fd82Sopenharmony_ci#include "hal_tick.h"
19a3e0fd82Sopenharmony_ci#include "securec.h"
20a3e0fd82Sopenharmony_ci
21a3e0fd82Sopenharmony_cinamespace OHOS {
22a3e0fd82Sopenharmony_ciconst uint8_t* CacheEntry::GetImgData() const
23a3e0fd82Sopenharmony_ci{
24a3e0fd82Sopenharmony_ci    return dsc_.imgInfo.data;
25a3e0fd82Sopenharmony_ci}
26a3e0fd82Sopenharmony_ci
27a3e0fd82Sopenharmony_ciRetCode CacheEntry::ReadLine(const Point& start, int16_t len, uint8_t* buf)
28a3e0fd82Sopenharmony_ci{
29a3e0fd82Sopenharmony_ci    RetCode ret;
30a3e0fd82Sopenharmony_ci    if (dsc_.decoder != nullptr) {
31a3e0fd82Sopenharmony_ci        ret = dsc_.decoder->ReadLine(dsc_, start, len, buf);
32a3e0fd82Sopenharmony_ci    } else {
33a3e0fd82Sopenharmony_ci        ret = RetCode::FAIL;
34a3e0fd82Sopenharmony_ci    }
35a3e0fd82Sopenharmony_ci
36a3e0fd82Sopenharmony_ci    return ret;
37a3e0fd82Sopenharmony_ci}
38a3e0fd82Sopenharmony_ci
39a3e0fd82Sopenharmony_civoid CacheEntry::Clear()
40a3e0fd82Sopenharmony_ci{
41a3e0fd82Sopenharmony_ci    if (dsc_.decoder != nullptr) {
42a3e0fd82Sopenharmony_ci        dsc_.decoder->Close(dsc_);
43a3e0fd82Sopenharmony_ci    }
44a3e0fd82Sopenharmony_ci
45a3e0fd82Sopenharmony_ci    dsc_.decoder = nullptr;
46a3e0fd82Sopenharmony_ci    ClearSrc();
47a3e0fd82Sopenharmony_ci    dsc_.imgInfo.data = nullptr;
48a3e0fd82Sopenharmony_ci    dsc_.fd = -1;
49a3e0fd82Sopenharmony_ci    dsc_.srcType = IMG_SRC_UNKNOWN;
50a3e0fd82Sopenharmony_ci    life_ = 0;
51a3e0fd82Sopenharmony_ci}
52a3e0fd82Sopenharmony_ci
53a3e0fd82Sopenharmony_civoid CacheEntry::ClearSrc()
54a3e0fd82Sopenharmony_ci{
55a3e0fd82Sopenharmony_ci    if (dsc_.srcType == IMG_SRC_FILE) {
56a3e0fd82Sopenharmony_ci        UIFree(const_cast<char*>(dsc_.path));
57a3e0fd82Sopenharmony_ci    }
58a3e0fd82Sopenharmony_ci    dsc_.path = nullptr;
59a3e0fd82Sopenharmony_ci}
60a3e0fd82Sopenharmony_ci
61a3e0fd82Sopenharmony_ciRetCode CacheEntry::SetSrc(const char* path)
62a3e0fd82Sopenharmony_ci{
63a3e0fd82Sopenharmony_ci    ClearSrc();
64a3e0fd82Sopenharmony_ci    if (dsc_.srcType == IMG_SRC_FILE) {
65a3e0fd82Sopenharmony_ci        size_t strLen = strlen(path);
66a3e0fd82Sopenharmony_ci        if (strLen > MAX_SRC_LENGTH) {
67a3e0fd82Sopenharmony_ci            return RetCode::FAIL;
68a3e0fd82Sopenharmony_ci        }
69a3e0fd82Sopenharmony_ci        char* newStr = static_cast<char*>(UIMalloc(static_cast<uint32_t>(strLen) + 1));
70a3e0fd82Sopenharmony_ci        if (newStr == nullptr) {
71a3e0fd82Sopenharmony_ci            return RetCode::FAIL;
72a3e0fd82Sopenharmony_ci        }
73a3e0fd82Sopenharmony_ci        if (memcpy_s(newStr, strLen + 1, path, strLen) != EOK) {
74a3e0fd82Sopenharmony_ci            UIFree(reinterpret_cast<void*>(newStr));
75a3e0fd82Sopenharmony_ci            newStr = nullptr;
76a3e0fd82Sopenharmony_ci            return RetCode::FAIL;
77a3e0fd82Sopenharmony_ci        }
78a3e0fd82Sopenharmony_ci        newStr[strLen] = '\0';
79a3e0fd82Sopenharmony_ci        dsc_.path = newStr;
80a3e0fd82Sopenharmony_ci    } else {
81a3e0fd82Sopenharmony_ci        dsc_.path = path;
82a3e0fd82Sopenharmony_ci    }
83a3e0fd82Sopenharmony_ci    return RetCode::OK;
84a3e0fd82Sopenharmony_ci}
85a3e0fd82Sopenharmony_ci
86a3e0fd82Sopenharmony_ciCacheManager& CacheManager::GetInstance()
87a3e0fd82Sopenharmony_ci{
88a3e0fd82Sopenharmony_ci    static CacheManager instance;
89a3e0fd82Sopenharmony_ci    return instance;
90a3e0fd82Sopenharmony_ci}
91a3e0fd82Sopenharmony_ci
92a3e0fd82Sopenharmony_ciRetCode CacheManager::Init(uint16_t size)
93a3e0fd82Sopenharmony_ci{
94a3e0fd82Sopenharmony_ci    if ((size == 0) || (size > DEFAULT_MAX_CACHE_ENTRY_NUM)) {
95a3e0fd82Sopenharmony_ci        return RetCode::FAIL;
96a3e0fd82Sopenharmony_ci    }
97a3e0fd82Sopenharmony_ci    Reset();
98a3e0fd82Sopenharmony_ci    if (entryArr_ != nullptr) {
99a3e0fd82Sopenharmony_ci        UIFree(reinterpret_cast<void*>(entryArr_));
100a3e0fd82Sopenharmony_ci    }
101a3e0fd82Sopenharmony_ci
102a3e0fd82Sopenharmony_ci    uint32_t tmpCacheSize = size * sizeof(CacheEntry);
103a3e0fd82Sopenharmony_ci    entryArr_ = static_cast<CacheEntry*>(UIMalloc(tmpCacheSize));
104a3e0fd82Sopenharmony_ci    if (entryArr_ == nullptr) {
105a3e0fd82Sopenharmony_ci        size_ = 0;
106a3e0fd82Sopenharmony_ci        return RetCode::FAIL;
107a3e0fd82Sopenharmony_ci    }
108a3e0fd82Sopenharmony_ci
109a3e0fd82Sopenharmony_ci    if (memset_s(entryArr_, tmpCacheSize, 0, tmpCacheSize) != EOK) {
110a3e0fd82Sopenharmony_ci        UIFree(reinterpret_cast<void*>(entryArr_));
111a3e0fd82Sopenharmony_ci        entryArr_ = nullptr;
112a3e0fd82Sopenharmony_ci        return RetCode::FAIL;
113a3e0fd82Sopenharmony_ci    }
114a3e0fd82Sopenharmony_ci
115a3e0fd82Sopenharmony_ci    size_ = size;
116a3e0fd82Sopenharmony_ci    return RetCode::OK;
117a3e0fd82Sopenharmony_ci}
118a3e0fd82Sopenharmony_ci
119a3e0fd82Sopenharmony_ciRetCode CacheManager::Open(const char* path, const Style& style, CacheEntry& entry)
120a3e0fd82Sopenharmony_ci{
121a3e0fd82Sopenharmony_ci    if ((path == nullptr) || (GetSize() <= 0)) {
122a3e0fd82Sopenharmony_ci        return RetCode::FAIL;
123a3e0fd82Sopenharmony_ci    }
124a3e0fd82Sopenharmony_ci
125a3e0fd82Sopenharmony_ci    AgingAll();
126a3e0fd82Sopenharmony_ci    uint16_t indexHitted = 0;
127a3e0fd82Sopenharmony_ci    RetCode ret = GetIndex(path, indexHitted);
128a3e0fd82Sopenharmony_ci    if (ret == RetCode::OK) {
129a3e0fd82Sopenharmony_ci        ReadToCache(entryArr_[indexHitted]);
130a3e0fd82Sopenharmony_ci        entry = entryArr_[indexHitted];
131a3e0fd82Sopenharmony_ci        return RetCode::OK;
132a3e0fd82Sopenharmony_ci    }
133a3e0fd82Sopenharmony_ci
134a3e0fd82Sopenharmony_ci    SelectEntryToReplace(indexHitted);
135a3e0fd82Sopenharmony_ci    if ((entryArr_[indexHitted].dsc_.path != nullptr) && (entryArr_[indexHitted].dsc_.decoder != nullptr)) {
136a3e0fd82Sopenharmony_ci        entryArr_[indexHitted].dsc_.decoder->Close(entryArr_[indexHitted].dsc_);
137a3e0fd82Sopenharmony_ci    }
138a3e0fd82Sopenharmony_ci
139a3e0fd82Sopenharmony_ci    uint32_t startTime = HALTick::GetInstance().GetTime();
140a3e0fd82Sopenharmony_ci    entryArr_[indexHitted].life_ = 0;
141a3e0fd82Sopenharmony_ci
142a3e0fd82Sopenharmony_ci    ret = TryDecode(path, style, entryArr_[indexHitted]);
143a3e0fd82Sopenharmony_ci    if (ret != RetCode::OK) {
144a3e0fd82Sopenharmony_ci        return ret;
145a3e0fd82Sopenharmony_ci    }
146a3e0fd82Sopenharmony_ci    ReadToCache(entryArr_[indexHitted]);
147a3e0fd82Sopenharmony_ci    entryArr_[indexHitted].life_ = HALTick::GetInstance().GetElapseTime(startTime);
148a3e0fd82Sopenharmony_ci    entry = entryArr_[indexHitted];
149a3e0fd82Sopenharmony_ci    return RetCode::OK;
150a3e0fd82Sopenharmony_ci}
151a3e0fd82Sopenharmony_ci
152a3e0fd82Sopenharmony_ciRetCode CacheManager::Close(const char* path)
153a3e0fd82Sopenharmony_ci{
154a3e0fd82Sopenharmony_ci    if (path == nullptr) {
155a3e0fd82Sopenharmony_ci        return RetCode::FAIL;
156a3e0fd82Sopenharmony_ci    }
157a3e0fd82Sopenharmony_ci
158a3e0fd82Sopenharmony_ci    for (uint16_t index = 0; index < GetSize(); index++) {
159a3e0fd82Sopenharmony_ci        if (entryArr_[index].dsc_.srcType == IMG_SRC_FILE) {
160a3e0fd82Sopenharmony_ci            if (entryArr_[index].dsc_.path == nullptr) {
161a3e0fd82Sopenharmony_ci                continue;
162a3e0fd82Sopenharmony_ci            }
163a3e0fd82Sopenharmony_ci            if (strcmp(entryArr_[index].dsc_.path, path) == 0) {
164a3e0fd82Sopenharmony_ci                Clear(entryArr_[index]);
165a3e0fd82Sopenharmony_ci                break;
166a3e0fd82Sopenharmony_ci            }
167a3e0fd82Sopenharmony_ci        } else {
168a3e0fd82Sopenharmony_ci            if (entryArr_[index].dsc_.path == path) {
169a3e0fd82Sopenharmony_ci                Clear(entryArr_[index]);
170a3e0fd82Sopenharmony_ci                break;
171a3e0fd82Sopenharmony_ci            }
172a3e0fd82Sopenharmony_ci        }
173a3e0fd82Sopenharmony_ci    }
174a3e0fd82Sopenharmony_ci
175a3e0fd82Sopenharmony_ci    return RetCode::OK;
176a3e0fd82Sopenharmony_ci}
177a3e0fd82Sopenharmony_ci
178a3e0fd82Sopenharmony_cibool CacheManager::GetImageHeader(const char* path, ImageHeader& header)
179a3e0fd82Sopenharmony_ci{
180a3e0fd82Sopenharmony_ci    CacheEntry entry;
181a3e0fd82Sopenharmony_ci    Style useless;
182a3e0fd82Sopenharmony_ci    RetCode ret = Open(path, useless, entry);
183a3e0fd82Sopenharmony_ci    if (ret != RetCode::OK) {
184a3e0fd82Sopenharmony_ci        GRAPHIC_LOGW("CacheManager::GetImageHeader Image get info found unknown src type\n");
185a3e0fd82Sopenharmony_ci        return false;
186a3e0fd82Sopenharmony_ci    }
187a3e0fd82Sopenharmony_ci
188a3e0fd82Sopenharmony_ci    header = entry.GetImgHeader();
189a3e0fd82Sopenharmony_ci    return true;
190a3e0fd82Sopenharmony_ci}
191a3e0fd82Sopenharmony_ci
192a3e0fd82Sopenharmony_ciRetCode CacheManager::Reset()
193a3e0fd82Sopenharmony_ci{
194a3e0fd82Sopenharmony_ci    if (entryArr_ == nullptr) {
195a3e0fd82Sopenharmony_ci        return RetCode::OK;
196a3e0fd82Sopenharmony_ci    }
197a3e0fd82Sopenharmony_ci
198a3e0fd82Sopenharmony_ci    for (uint16_t index = 0; index < GetSize(); index++) {
199a3e0fd82Sopenharmony_ci        if (entryArr_[index].dsc_.path != nullptr) {
200a3e0fd82Sopenharmony_ci            Clear(entryArr_[index]);
201a3e0fd82Sopenharmony_ci        }
202a3e0fd82Sopenharmony_ci    }
203a3e0fd82Sopenharmony_ci
204a3e0fd82Sopenharmony_ci    return RetCode::OK;
205a3e0fd82Sopenharmony_ci}
206a3e0fd82Sopenharmony_ci
207a3e0fd82Sopenharmony_ciRetCode CacheManager::ReadToCache(CacheEntry& entry)
208a3e0fd82Sopenharmony_ci{
209a3e0fd82Sopenharmony_ci    if (entry.dsc_.decoder == nullptr) {
210a3e0fd82Sopenharmony_ci        return RetCode::FAIL;
211a3e0fd82Sopenharmony_ci    }
212a3e0fd82Sopenharmony_ci    return entry.dsc_.decoder->ReadToCache(entry.dsc_);
213a3e0fd82Sopenharmony_ci}
214a3e0fd82Sopenharmony_ci
215a3e0fd82Sopenharmony_civoid CacheManager::Clear(CacheEntry& entry)
216a3e0fd82Sopenharmony_ci{
217a3e0fd82Sopenharmony_ci    entry.Clear();
218a3e0fd82Sopenharmony_ci}
219a3e0fd82Sopenharmony_ci
220a3e0fd82Sopenharmony_civoid CacheManager::AgingAll(int32_t time)
221a3e0fd82Sopenharmony_ci{
222a3e0fd82Sopenharmony_ci    for (uint16_t index = 0; index < GetSize(); index++) {
223a3e0fd82Sopenharmony_ci        if (entryArr_[index].life_ > INT32_MIN + AGING_INTERVAL) {
224a3e0fd82Sopenharmony_ci            entryArr_[index].life_ -= time;
225a3e0fd82Sopenharmony_ci        }
226a3e0fd82Sopenharmony_ci    }
227a3e0fd82Sopenharmony_ci}
228a3e0fd82Sopenharmony_ci
229a3e0fd82Sopenharmony_ciRetCode CacheManager::GetIndex(const char* path, uint16_t& hittedIndex)
230a3e0fd82Sopenharmony_ci{
231a3e0fd82Sopenharmony_ci    for (uint16_t index = 0; index < GetSize(); index++) {
232a3e0fd82Sopenharmony_ci        if (entryArr_[index].dsc_.srcType == IMG_SRC_FILE) {
233a3e0fd82Sopenharmony_ci            if ((entryArr_[index].dsc_.path != nullptr) && !strcmp(path, entryArr_[index].dsc_.path)) {
234a3e0fd82Sopenharmony_ci                entryArr_[index].life_ += entryArr_[index].dsc_.timeToOpen * LIFE_GAIN_INTERVAL;
235a3e0fd82Sopenharmony_ci                if (entryArr_[index].life_ > LIFE_LIMIT) {
236a3e0fd82Sopenharmony_ci                    entryArr_[index].life_ = LIFE_LIMIT;
237a3e0fd82Sopenharmony_ci                }
238a3e0fd82Sopenharmony_ci                hittedIndex = index;
239a3e0fd82Sopenharmony_ci                return RetCode::OK;
240a3e0fd82Sopenharmony_ci            }
241a3e0fd82Sopenharmony_ci        } else {
242a3e0fd82Sopenharmony_ci            ImageInfo* imgDsc = reinterpret_cast<ImageInfo*>(const_cast<char*>(path));
243a3e0fd82Sopenharmony_ci            if ((entryArr_[index].dsc_.path == path) && (entryArr_[index].dsc_.imgInfo.data == imgDsc->data)) {
244a3e0fd82Sopenharmony_ci                entryArr_[index].life_ += entryArr_[index].dsc_.timeToOpen * LIFE_GAIN_INTERVAL;
245a3e0fd82Sopenharmony_ci                if (entryArr_[index].life_ > LIFE_LIMIT) {
246a3e0fd82Sopenharmony_ci                    entryArr_[index].life_ = LIFE_LIMIT;
247a3e0fd82Sopenharmony_ci                }
248a3e0fd82Sopenharmony_ci                hittedIndex = index;
249a3e0fd82Sopenharmony_ci                return RetCode::OK;
250a3e0fd82Sopenharmony_ci            }
251a3e0fd82Sopenharmony_ci        }
252a3e0fd82Sopenharmony_ci    }
253a3e0fd82Sopenharmony_ci
254a3e0fd82Sopenharmony_ci    return RetCode::FAIL;
255a3e0fd82Sopenharmony_ci}
256a3e0fd82Sopenharmony_ci
257a3e0fd82Sopenharmony_ciRetCode CacheManager::SelectEntryToReplace(uint16_t& selectedIndex)
258a3e0fd82Sopenharmony_ci{
259a3e0fd82Sopenharmony_ci    selectedIndex = 0;
260a3e0fd82Sopenharmony_ci    for (uint16_t index = 0; index < GetSize(); index++) {
261a3e0fd82Sopenharmony_ci        if (entryArr_[index].life_ < entryArr_[selectedIndex].life_) {
262a3e0fd82Sopenharmony_ci            selectedIndex = index;
263a3e0fd82Sopenharmony_ci        }
264a3e0fd82Sopenharmony_ci    }
265a3e0fd82Sopenharmony_ci
266a3e0fd82Sopenharmony_ci    return RetCode::OK;
267a3e0fd82Sopenharmony_ci}
268a3e0fd82Sopenharmony_ci
269a3e0fd82Sopenharmony_ciRetCode CacheManager::TryDecode(const char* path, const Style& style, CacheEntry& entry)
270a3e0fd82Sopenharmony_ci{
271a3e0fd82Sopenharmony_ci    FileImgDecoder* decoder = &(FileImgDecoder::GetInstance());
272a3e0fd82Sopenharmony_ci    if (decoder == nullptr) {
273a3e0fd82Sopenharmony_ci        Clear(entry);
274a3e0fd82Sopenharmony_ci        return RetCode::FAIL;
275a3e0fd82Sopenharmony_ci    }
276a3e0fd82Sopenharmony_ci
277a3e0fd82Sopenharmony_ci    entry.dsc_.srcType = IMG_SRC_FILE;
278a3e0fd82Sopenharmony_ci    RetCode ret = entry.SetSrc(path);
279a3e0fd82Sopenharmony_ci    if (ret != RetCode::OK) {
280a3e0fd82Sopenharmony_ci        Clear(entry);
281a3e0fd82Sopenharmony_ci        return ret;
282a3e0fd82Sopenharmony_ci    }
283a3e0fd82Sopenharmony_ci    entry.dsc_.decoder = decoder;
284a3e0fd82Sopenharmony_ci
285a3e0fd82Sopenharmony_ci    ret = entry.dsc_.decoder->GetHeader(entry.dsc_);
286a3e0fd82Sopenharmony_ci    if (ret != RetCode::OK) {
287a3e0fd82Sopenharmony_ci        Clear(entry);
288a3e0fd82Sopenharmony_ci        return ret;
289a3e0fd82Sopenharmony_ci    }
290a3e0fd82Sopenharmony_ci
291a3e0fd82Sopenharmony_ci    ret = entry.dsc_.decoder->Open(entry.dsc_);
292a3e0fd82Sopenharmony_ci    if (ret != RetCode::OK) {
293a3e0fd82Sopenharmony_ci        Clear(entry);
294a3e0fd82Sopenharmony_ci        return ret;
295a3e0fd82Sopenharmony_ci    }
296a3e0fd82Sopenharmony_ci
297a3e0fd82Sopenharmony_ci    return ret;
298a3e0fd82Sopenharmony_ci}
299a3e0fd82Sopenharmony_ci} // namespace OHOS
300