1 /* 2 * Copyright (c) 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 "util.h" 17 18 #include <event_handler.h> 19 #include <fstream> 20 #include <securec.h> 21 #include <sstream> 22 23 namespace OHOS { 24 constexpr const float HALF = 2.0; 25 constexpr const float RADIO = 360.0; 26 PostTask(std::function<void ()> func,uint32_t delayTime)27 void PostTask(std::function<void()> func, uint32_t delayTime) 28 { 29 auto handler = AppExecFwk::EventHandler::Current(); 30 if (handler) { 31 handler->PostTask(func, delayTime); 32 } 33 } 34 IsFileExisted(const std::string & filePath)35 bool IsFileExisted(const std::string& filePath) 36 { 37 if (filePath.empty()) { 38 LOGE("check filepath is empty"); 39 return false; 40 } 41 char newpath[PATH_MAX + 1] = { 0x00 }; 42 if (strlen(filePath.c_str()) > PATH_MAX || realpath(filePath.c_str(), newpath) == nullptr) { 43 LOGE("check filepath fail! %{public}s %{public}d %{public}s", filePath.c_str(), errno, ::strerror(errno)); 44 return false; 45 } 46 struct stat info = {0}; 47 if (stat(newpath, &info) != 0) { 48 LOGE("stat filepath fail! %{public}s %{public}d %{public}s", filePath.c_str(), errno, ::strerror(errno)); 49 return false; 50 } 51 return true; 52 } 53 ParseBootConfig(const std::string & path,int32_t & duration,bool & isCompatible,bool & isMultiDisplay,std::vector<BootAnimationConfig> & configs)54 bool ParseBootConfig(const std::string& path, int32_t& duration, bool& isCompatible, bool& isMultiDisplay, 55 std::vector<BootAnimationConfig>& configs) 56 { 57 char newpath[PATH_MAX + 1] = { 0x00 }; 58 if (strlen(path.c_str()) > PATH_MAX || realpath(path.c_str(), newpath) == nullptr) { 59 LOGE("check config path fail! %{public}s %{public}d %{public}s", path.c_str(), errno, ::strerror(errno)); 60 return false; 61 } 62 63 std::ifstream configFile; 64 configFile.open(newpath); 65 std::stringstream JFilterParamsStream; 66 JFilterParamsStream << configFile.rdbuf(); 67 configFile.close(); 68 std::string JParamsString = JFilterParamsStream.str(); 69 70 cJSON* overallData = cJSON_Parse(JParamsString.c_str()); 71 if (overallData == nullptr) { 72 LOGE("can not parse config to json"); 73 return false; 74 } 75 cJSON_bool isNewConfig = cJSON_HasObjectItem(overallData, "screen_config"); 76 if (!isNewConfig) { 77 isCompatible = true; 78 ParseOldConfigFile(overallData, configs); 79 } else { 80 ParseNewConfigFile(overallData, isMultiDisplay, configs); 81 } 82 ParseBootDuration(overallData, duration); 83 cJSON_Delete(overallData); 84 return true; 85 } 86 ParseOldConfigFile(cJSON * data,std::vector<BootAnimationConfig> & configs)87 void ParseOldConfigFile(cJSON* data, std::vector<BootAnimationConfig>& configs) 88 { 89 LOGD("ParseOldConfigFile"); 90 BootAnimationConfig config; 91 cJSON* custPicPath = cJSON_GetObjectItem(data, "cust.bootanimation.pics"); 92 if (custPicPath != nullptr && cJSON_IsString(custPicPath)) { 93 config.picZipPath = custPicPath->valuestring; 94 LOGI("cust piczip path: %{public}s", config.picZipPath.c_str()); 95 } 96 cJSON* custSoundPath = cJSON_GetObjectItem(data, "cust.bootanimation.sounds"); 97 if (custSoundPath != nullptr && cJSON_IsString(custSoundPath)) { 98 config.soundPath = custSoundPath->valuestring; 99 LOGI("cust sound path: %{public}s", config.soundPath.c_str()); 100 } 101 cJSON* custVideoDefaultPath = cJSON_GetObjectItem(data, "cust.bootanimation.video"); 102 if (custVideoDefaultPath != nullptr && cJSON_IsString(custVideoDefaultPath)) { 103 config.videoDefaultPath = custVideoDefaultPath->valuestring; 104 LOGI("cust video path: %{public}s", config.videoDefaultPath.c_str()); 105 } 106 cJSON* custVideoExtraPath = cJSON_GetObjectItem(data, "cust.bootanimation.video.extra"); 107 if (custVideoExtraPath != nullptr && cJSON_IsString(custVideoExtraPath)) { 108 config.videoExtraPath = custVideoExtraPath->valuestring; 109 LOGI("cust extra video path: %{public}s", config.videoExtraPath.c_str()); 110 } 111 cJSON* rotateScreenJson = cJSON_GetObjectItem(data, "cust.bootanimation.rotate.screenid"); 112 if (rotateScreenJson != nullptr && cJSON_IsString(rotateScreenJson)) { 113 config.rotateScreenId = std::stoi(rotateScreenJson->valuestring); 114 LOGI("cust rotateScreenId: %{public}d", config.rotateScreenId); 115 } 116 cJSON* rotateDegreeJson = cJSON_GetObjectItem(data, "cust.bootanimation.rotate.degree"); 117 if (rotateDegreeJson != nullptr && cJSON_IsString(rotateDegreeJson)) { 118 config.rotateDegree = std::stoi(rotateDegreeJson->valuestring); 119 LOGI("cust rotateDegree: %{public}d", config.rotateDegree); 120 } 121 configs.emplace_back(config); 122 } 123 ParseNewConfigFile(cJSON * data,bool & isMultiDisplay,std::vector<BootAnimationConfig> & configs)124 void ParseNewConfigFile(cJSON* data, bool& isMultiDisplay, std::vector<BootAnimationConfig>& configs) 125 { 126 LOGD("ParseNewConfigFile"); 127 cJSON* isSupport = cJSON_GetObjectItem(data, "cust.bootanimation.multi_display"); 128 if (isSupport != nullptr && cJSON_IsBool(isSupport)) { 129 if (cJSON_IsTrue(isSupport)) { 130 isMultiDisplay = true; 131 } 132 } 133 LOGI("isMultiDisplay: %{public}d", isMultiDisplay); 134 135 cJSON* screens = cJSON_GetObjectItem(data, "screen_config"); 136 if (screens != nullptr) { 137 BootAnimationConfig config; 138 cJSON* item = screens->child; 139 while (item != nullptr) { 140 cJSON* screenIdJson = cJSON_GetObjectItem(item, "cust.bootanimation.screen_id"); 141 if (screenIdJson != nullptr && cJSON_IsString(screenIdJson)) { 142 config.screenId = std::stoul(screenIdJson->valuestring); 143 LOGI("screenId: " BPUBU64 "", config.screenId); 144 } 145 cJSON* custPicPath = cJSON_GetObjectItem(item, "cust.bootanimation.pics"); 146 if (custPicPath != nullptr && cJSON_IsString(custPicPath)) { 147 config.picZipPath = custPicPath->valuestring; 148 LOGI("cust piczip path: %{public}s", config.picZipPath.c_str()); 149 } 150 cJSON* custSoundPath = cJSON_GetObjectItem(item, "cust.bootanimation.sounds"); 151 if (custSoundPath != nullptr && cJSON_IsString(custSoundPath)) { 152 config.soundPath = custSoundPath->valuestring; 153 LOGI("cust sound path: %{public}s", config.soundPath.c_str()); 154 } 155 cJSON* custVideoDefaultPath = cJSON_GetObjectItem(item, "cust.bootanimation.video_default"); 156 if (custVideoDefaultPath != nullptr && cJSON_IsString(custVideoDefaultPath)) { 157 config.videoDefaultPath = custVideoDefaultPath->valuestring; 158 LOGI("cust default video path: %{public}s", config.videoDefaultPath.c_str()); 159 } 160 cJSON* rotateDegreeJson = cJSON_GetObjectItem(item, "cust.bootanimation.rotate_degree"); 161 if (rotateDegreeJson != nullptr && cJSON_IsString(rotateDegreeJson)) { 162 config.rotateDegree = std::stoi(rotateDegreeJson->valuestring); 163 LOGI("cust rotateDegree: %{public}d", config.rotateDegree); 164 } 165 cJSON* extraVideoPath = cJSON_GetObjectItem(item, "cust.bootanimation.video_extensions"); 166 if (extraVideoPath != nullptr && cJSON_IsArray(extraVideoPath)) { 167 ParseVideoExtraPath(extraVideoPath, config); 168 } 169 configs.emplace_back(config); 170 item = item->next; 171 } 172 } 173 } 174 ParseVideoExtraPath(cJSON * data,BootAnimationConfig & config)175 void ParseVideoExtraPath(cJSON* data, BootAnimationConfig& config) 176 { 177 int size = cJSON_GetArraySize(data); 178 for (int index = 0; index < size; index++) { 179 cJSON* extraPath = cJSON_GetArrayItem(data, index); 180 if (extraPath != nullptr && cJSON_IsString(extraPath)) { 181 config.videoExtPath.emplace_back(extraPath->valuestring); 182 } 183 } 184 } 185 ParseBootDuration(cJSON * data,int32_t & duration)186 void ParseBootDuration(cJSON* data, int32_t& duration) 187 { 188 cJSON* durationJson = cJSON_GetObjectItem(data, "cust.bootanimation.duration"); 189 if (durationJson != nullptr && cJSON_IsString(durationJson)) { 190 duration = std::stoi(durationJson->valuestring); 191 LOGI("cust duration: %{public}d", duration); 192 } 193 } 194 ReadZipFile(const std::string & srcFilePath,ImageStructVec & imgVec,FrameRateConfig & frameConfig)195 bool ReadZipFile(const std::string& srcFilePath, ImageStructVec& imgVec, FrameRateConfig& frameConfig) 196 { 197 unzFile zipFile = unzOpen2(srcFilePath.c_str(), nullptr); 198 if (zipFile == nullptr) { 199 LOGE("Open zipFile fail: %{public}s", srcFilePath.c_str()); 200 return false; 201 } 202 203 unz_global_info globalInfo; 204 if (unzGetGlobalInfo(zipFile, &globalInfo) != UNZ_OK) { 205 LOGE("Get ZipGlobalInfo fail"); 206 return CloseZipFile(zipFile, false); 207 } 208 209 LOGD("read zip file num: %{public}ld", globalInfo.number_entry); 210 for (unsigned long i = 0; i < globalInfo.number_entry; ++i) { 211 unz_file_info fileInfo; 212 char filename[MAX_FILE_NAME] = {0}; 213 if (unzGetCurrentFileInfo(zipFile, &fileInfo, filename, MAX_FILE_NAME, nullptr, 0, nullptr, 0) != UNZ_OK) { 214 return CloseZipFile(zipFile, false); 215 } 216 size_t length = strlen(filename); 217 if (length > MAX_FILE_NAME || length == 0) { 218 return CloseZipFile(zipFile, false); 219 } 220 if (filename[length - 1] != '/') { 221 if (unzOpenCurrentFile(zipFile) != UNZ_OK) { 222 return CloseZipFile(zipFile, false); 223 } 224 std::string name = std::string(filename); 225 size_t npos = name.find_last_of("//"); 226 if (npos != std::string::npos) { 227 name = name.substr(npos + 1, name.length()); 228 } 229 if (!ReadImageFile(zipFile, name, imgVec, frameConfig, fileInfo.uncompressed_size)) { 230 LOGE("read zip deal single file failed"); 231 unzCloseCurrentFile(zipFile); 232 return CloseZipFile(zipFile, false); 233 } 234 unzCloseCurrentFile(zipFile); 235 } 236 if (i < (globalInfo.number_entry - 1)) { 237 if (unzGoToNextFile(zipFile) != UNZ_OK) { 238 return CloseZipFile(zipFile, false); 239 } 240 } 241 } 242 return CloseZipFile(zipFile, true); 243 } 244 CloseZipFile(const unzFile zipFile,bool ret)245 bool CloseZipFile(const unzFile zipFile, bool ret) 246 { 247 unzClose(zipFile); 248 return ret; 249 } 250 SortZipFile(ImageStructVec & imgVec)251 void SortZipFile(ImageStructVec& imgVec) 252 { 253 if (imgVec.size() == 0) { 254 return; 255 } 256 257 sort(imgVec.begin(), imgVec.end(), [](std::shared_ptr<ImageStruct> image1, 258 std::shared_ptr<ImageStruct> image2) 259 -> bool {return image1->fileName < image2->fileName;}); 260 } 261 ReadImageFile(const unzFile zipFile,const std::string & fileName,ImageStructVec & imgVec,FrameRateConfig & frameConfig,unsigned long fileSize)262 bool ReadImageFile(const unzFile zipFile, const std::string& fileName, ImageStructVec& imgVec, 263 FrameRateConfig& frameConfig, unsigned long fileSize) 264 { 265 if (zipFile == nullptr) { 266 LOGE("ReadImageFile failed, zip is null"); 267 return false; 268 } 269 int readLen = UNZ_OK; 270 int totalLen = 0; 271 int size = static_cast<int>(fileSize); 272 char readBuffer[READ_SIZE] = {0}; 273 std::shared_ptr<ImageStruct> imageStruct = std::make_shared<ImageStruct>(); 274 imageStruct->memPtr.SetBufferSize(fileSize); 275 do { 276 readLen = unzReadCurrentFile(zipFile, readBuffer, READ_SIZE); 277 if (readLen < 0) { 278 LOGE("unzReadCurrentFile length error"); 279 return false; 280 } 281 if (imageStruct->memPtr.memBuffer == nullptr) { 282 LOGE("ReadImageFile memPtr is null"); 283 return false; 284 } 285 if (memcpy_s(imageStruct->memPtr.memBuffer + totalLen, size - totalLen, \ 286 readBuffer, readLen) == EOK) { 287 totalLen += readLen; 288 } 289 } while (readLen > 0); 290 291 if (totalLen > 0) { 292 LOGD("fileName: %{public}s, fileSize: %{public}d, totalLen: %{public}d", fileName.c_str(), size, totalLen); 293 if (strstr(fileName.c_str(), BOOT_PIC_CONFIG_FILE.c_str()) != nullptr) { 294 ParseImageConfig(imageStruct->memPtr.memBuffer, totalLen, frameConfig); 295 } else { 296 CheckImageData(fileName, imageStruct, totalLen, imgVec); 297 } 298 } 299 return true; 300 } 301 ParseImageConfig(const char * fileBuffer,int totalsize,FrameRateConfig & frameConfig)302 bool ParseImageConfig(const char* fileBuffer, int totalsize, FrameRateConfig& frameConfig) 303 { 304 std::string JParamsString; 305 JParamsString.assign(fileBuffer, totalsize); 306 cJSON* overallData = cJSON_Parse(JParamsString.c_str()); 307 if (overallData == nullptr) { 308 LOGE("parse image config failed"); 309 return false; 310 } 311 cJSON* frameRate = cJSON_GetObjectItem(overallData, "FrameRate"); 312 if (frameRate != nullptr && cJSON_IsNumber(frameRate)) { 313 frameConfig.frameRate = frameRate->valueint; 314 LOGI("freq: %{public}d", frameConfig.frameRate); 315 } 316 cJSON_Delete(overallData); 317 return true; 318 } 319 CheckImageData(const std::string & fileName,std::shared_ptr<ImageStruct> imageStruct,int32_t bufferLen,ImageStructVec & imgVec)320 bool CheckImageData(const std::string& fileName, std::shared_ptr<ImageStruct> imageStruct, 321 int32_t bufferLen, ImageStructVec& imgVec) 322 { 323 if (imageStruct->memPtr.memBuffer == nullptr) { 324 LOGE("json file buffer is null"); 325 return false; 326 } 327 auto data = std::make_shared<Rosen::Drawing::Data>(); 328 data->BuildFromMalloc(imageStruct->memPtr.memBuffer, bufferLen); 329 if (data->GetData() == nullptr) { 330 LOGE("data memory data is null. update data failed"); 331 return false; 332 } 333 imageStruct->memPtr.setOwnerShip(data); 334 imageStruct->fileName = fileName; 335 imageStruct->imageData = std::make_shared<Rosen::Drawing::Image>(); 336 imageStruct->imageData->MakeFromEncoded(data); 337 imgVec.push_back(imageStruct); 338 return true; 339 } 340 341 /** 342 * Transate vp to pixel. 343 * 344 * @param sideLen The short side length of screen. 345 * @param vp vp value. 346 * @return Returns the font size. 347 */ TransalteVp2Pixel(const int32_t sideLen,const int32_t vp)348 int32_t TransalteVp2Pixel(const int32_t sideLen, const int32_t vp) 349 { 350 return static_cast<int32_t>(std::ceil(sideLen * HALF / RADIO) / HALF * vp); 351 } 352 } // namespace OHOS 353