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