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