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